@mcpmesh/sdk 0.9.11 → 1.0.0-beta.1

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 (94) hide show
  1. package/dist/__tests__/claude-handler.test.js +119 -71
  2. package/dist/__tests__/claude-handler.test.js.map +1 -1
  3. package/dist/__tests__/llm-agent-media.test.d.ts +8 -0
  4. package/dist/__tests__/llm-agent-media.test.d.ts.map +1 -0
  5. package/dist/__tests__/llm-agent-media.test.js +167 -0
  6. package/dist/__tests__/llm-agent-media.test.js.map +1 -0
  7. package/dist/__tests__/media-helpers.test.d.ts +7 -0
  8. package/dist/__tests__/media-helpers.test.d.ts.map +1 -0
  9. package/dist/__tests__/media-helpers.test.js +60 -0
  10. package/dist/__tests__/media-helpers.test.js.map +1 -0
  11. package/dist/__tests__/media-param.test.d.ts +7 -0
  12. package/dist/__tests__/media-param.test.d.ts.map +1 -0
  13. package/dist/__tests__/media-param.test.js +104 -0
  14. package/dist/__tests__/media-param.test.js.map +1 -0
  15. package/dist/__tests__/media-resolver.test.d.ts +8 -0
  16. package/dist/__tests__/media-resolver.test.d.ts.map +1 -0
  17. package/dist/__tests__/media-resolver.test.js +298 -0
  18. package/dist/__tests__/media-resolver.test.js.map +1 -0
  19. package/dist/__tests__/media-result.test.d.ts +5 -0
  20. package/dist/__tests__/media-result.test.d.ts.map +1 -0
  21. package/dist/__tests__/media-result.test.js +180 -0
  22. package/dist/__tests__/media-result.test.js.map +1 -0
  23. package/dist/__tests__/media-store.test.d.ts +7 -0
  24. package/dist/__tests__/media-store.test.d.ts.map +1 -0
  25. package/dist/__tests__/media-store.test.js +102 -0
  26. package/dist/__tests__/media-store.test.js.map +1 -0
  27. package/dist/__tests__/proxy-resource-link.test.d.ts +8 -0
  28. package/dist/__tests__/proxy-resource-link.test.d.ts.map +1 -0
  29. package/dist/__tests__/proxy-resource-link.test.js +175 -0
  30. package/dist/__tests__/proxy-resource-link.test.js.map +1 -0
  31. package/dist/agent.d.ts +1 -0
  32. package/dist/agent.d.ts.map +1 -1
  33. package/dist/agent.js +76 -10
  34. package/dist/agent.js.map +1 -1
  35. package/dist/api-runtime.d.ts.map +1 -1
  36. package/dist/api-runtime.js +7 -1
  37. package/dist/api-runtime.js.map +1 -1
  38. package/dist/config.d.ts +17 -0
  39. package/dist/config.d.ts.map +1 -1
  40. package/dist/config.js +19 -0
  41. package/dist/config.js.map +1 -1
  42. package/dist/debug.d.ts +1 -1
  43. package/dist/debug.d.ts.map +1 -1
  44. package/dist/express.d.ts.map +1 -1
  45. package/dist/express.js +33 -18
  46. package/dist/express.js.map +1 -1
  47. package/dist/index.d.ts +5 -2
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +6 -1
  50. package/dist/index.js.map +1 -1
  51. package/dist/llm-agent.d.ts +2 -0
  52. package/dist/llm-agent.d.ts.map +1 -1
  53. package/dist/llm-agent.js +62 -13
  54. package/dist/llm-agent.js.map +1 -1
  55. package/dist/llm-provider.d.ts +55 -16
  56. package/dist/llm-provider.d.ts.map +1 -1
  57. package/dist/llm-provider.js +321 -32
  58. package/dist/llm-provider.js.map +1 -1
  59. package/dist/media/index.d.ts +104 -0
  60. package/dist/media/index.d.ts.map +1 -0
  61. package/dist/media/index.js +135 -0
  62. package/dist/media/index.js.map +1 -0
  63. package/dist/media/media-store.d.ts +75 -0
  64. package/dist/media/media-store.d.ts.map +1 -0
  65. package/dist/media/media-store.js +217 -0
  66. package/dist/media/media-store.js.map +1 -0
  67. package/dist/media/resolver.d.ts +67 -0
  68. package/dist/media/resolver.d.ts.map +1 -0
  69. package/dist/media/resolver.js +311 -0
  70. package/dist/media/resolver.js.map +1 -0
  71. package/dist/media-param.d.ts +17 -0
  72. package/dist/media-param.d.ts.map +1 -0
  73. package/dist/media-param.js +32 -0
  74. package/dist/media-param.js.map +1 -0
  75. package/dist/provider-handlers/claude-handler.d.ts +21 -26
  76. package/dist/provider-handlers/claude-handler.d.ts.map +1 -1
  77. package/dist/provider-handlers/claude-handler.js +65 -45
  78. package/dist/provider-handlers/claude-handler.js.map +1 -1
  79. package/dist/provider-handlers/provider-handler.d.ts.map +1 -1
  80. package/dist/provider-handlers/provider-handler.js +5 -4
  81. package/dist/provider-handlers/provider-handler.js.map +1 -1
  82. package/dist/proxy.d.ts +29 -0
  83. package/dist/proxy.d.ts.map +1 -1
  84. package/dist/proxy.js +66 -21
  85. package/dist/proxy.js.map +1 -1
  86. package/dist/tls-config.d.ts +31 -0
  87. package/dist/tls-config.d.ts.map +1 -0
  88. package/dist/tls-config.js +102 -0
  89. package/dist/tls-config.js.map +1 -0
  90. package/dist/types.d.ts +63 -2
  91. package/dist/types.d.ts.map +1 -1
  92. package/dist/types.js +33 -1
  93. package/dist/types.js.map +1 -1
  94. package/package.json +3 -3
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Media module — public API for multimodal content storage and helpers.
3
+ */
4
+ export { type MediaStore, LocalMediaStore, S3MediaStore, getMediaStore, guessMimeType, _resetMediaStore, } from "./media-store.js";
5
+ export { formatForOpenai, resolveResourceLinks, resolveResourceLinksForToolMessage, resolveMediaAsUserMessage, hasResourceLink, TOOL_IMAGE_UNSUPPORTED_VENDORS, type ResolvedContent, } from "./resolver.js";
6
+ import { type ResolvedContent } from "./resolver.js";
7
+ import type { ResourceLink } from "fastmcp";
8
+ /**
9
+ * Upload binary data to the configured media store.
10
+ *
11
+ * @returns URI pointing to the stored blob (e.g. `file://...` or `s3://...`).
12
+ */
13
+ export declare function uploadMedia(data: Buffer, filename: string, mimeType: string): Promise<string>;
14
+ /**
15
+ * Build an MCP `resource_link` content item.
16
+ *
17
+ * This is the standard way for tools to return references to binary media
18
+ * (images, audio, PDFs, etc.) rather than embedding them inline.
19
+ *
20
+ * Returns a proper MCP ResourceLink that FastMCP sends as a `resource_link`
21
+ * content type in the MCP protocol response (not serialized as JSON text).
22
+ */
23
+ export declare function mediaResult(uri: string, name: string, mimeType: string, description?: string, size?: number): ResourceLink;
24
+ /**
25
+ * Convenience class: upload bytes and return a ResourceLink in one step.
26
+ *
27
+ * Usage:
28
+ * const link = await new MediaResult(pngBytes, "chart.png", "image/png").toResourceLink();
29
+ * // or use the standalone function:
30
+ * const link = await createMediaResult(pngBytes, "chart.png", "image/png");
31
+ */
32
+ export declare class MediaResult {
33
+ readonly data: Buffer;
34
+ readonly filename: string;
35
+ readonly mimeType: string;
36
+ readonly name?: string | undefined;
37
+ readonly description?: string | undefined;
38
+ constructor(data: Buffer, filename: string, mimeType: string, name?: string | undefined, description?: string | undefined);
39
+ toResourceLink(): Promise<ResourceLink>;
40
+ }
41
+ /**
42
+ * Upload bytes and return a ResourceLink in one step.
43
+ */
44
+ export declare function createMediaResult(data: Buffer, filename: string, mimeType: string, name?: string, description?: string): Promise<ResourceLink>;
45
+ /**
46
+ * Result of saving an upload to MediaStore.
47
+ */
48
+ export interface MediaUploadResult {
49
+ uri: string;
50
+ name: string;
51
+ mimeType: string;
52
+ size: number;
53
+ }
54
+ /**
55
+ * Save a file upload (e.g., from multer) to MediaStore and return the URI.
56
+ *
57
+ * Accepts objects with buffer/originalname/mimetype properties (multer format)
58
+ * or any object with data/name/mimeType properties.
59
+ */
60
+ export declare function saveUpload(file: {
61
+ buffer: Buffer;
62
+ originalname: string;
63
+ mimetype: string;
64
+ } | {
65
+ data: Buffer;
66
+ name: string;
67
+ mimeType: string;
68
+ }, options?: {
69
+ filename?: string;
70
+ mimeType?: string;
71
+ }): Promise<string>;
72
+ /**
73
+ * Save a file upload and return full metadata.
74
+ */
75
+ export declare function saveUploadResult(file: {
76
+ buffer: Buffer;
77
+ originalname: string;
78
+ mimetype: string;
79
+ } | {
80
+ data: Buffer;
81
+ name: string;
82
+ mimeType: string;
83
+ }, options?: {
84
+ filename?: string;
85
+ mimeType?: string;
86
+ }): Promise<MediaUploadResult>;
87
+ /**
88
+ * Resolve an array of media inputs to OpenAI-compatible image_url content parts.
89
+ *
90
+ * Each item is either:
91
+ * - A URI string (resolved via MediaStore.fetch())
92
+ * - An inline `{ data: Buffer; mimeType: string }` object
93
+ *
94
+ * Returns an array of ResolvedContent parts in OpenAI image_url format,
95
+ * which Vercel AI SDK converts to each vendor's native format.
96
+ *
97
+ * @param media - Array of URI strings or inline media objects
98
+ * @returns Array of OpenAI-compatible image_url content parts
99
+ */
100
+ export declare function resolveMediaInputs(media: Array<string | {
101
+ data: Buffer;
102
+ mimeType: string;
103
+ }>): Promise<ResolvedContent[]>;
104
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Media module — public API for multimodal content storage and helpers.
3
+ */
4
+ export { LocalMediaStore, S3MediaStore, getMediaStore, guessMimeType, _resetMediaStore, } from "./media-store.js";
5
+ export { formatForOpenai, resolveResourceLinks, resolveResourceLinksForToolMessage, resolveMediaAsUserMessage, hasResourceLink, TOOL_IMAGE_UNSUPPORTED_VENDORS, } from "./resolver.js";
6
+ import { getMediaStore } from "./media-store.js";
7
+ import { formatForOpenai } from "./resolver.js";
8
+ /**
9
+ * Upload binary data to the configured media store.
10
+ *
11
+ * @returns URI pointing to the stored blob (e.g. `file://...` or `s3://...`).
12
+ */
13
+ export async function uploadMedia(data, filename, mimeType) {
14
+ const store = getMediaStore();
15
+ return store.upload(data, filename, mimeType);
16
+ }
17
+ /**
18
+ * Build an MCP `resource_link` content item.
19
+ *
20
+ * This is the standard way for tools to return references to binary media
21
+ * (images, audio, PDFs, etc.) rather than embedding them inline.
22
+ *
23
+ * Returns a proper MCP ResourceLink that FastMCP sends as a `resource_link`
24
+ * content type in the MCP protocol response (not serialized as JSON text).
25
+ */
26
+ export function mediaResult(uri, name, mimeType, description, size) {
27
+ const result = { type: "resource_link", uri, name, mimeType };
28
+ if (description !== undefined)
29
+ result.description = description;
30
+ if (size !== undefined)
31
+ result._meta = { size };
32
+ return result;
33
+ }
34
+ // ---------------------------------------------------------------------------
35
+ // MediaResult class — upload + ResourceLink in one step
36
+ // ---------------------------------------------------------------------------
37
+ /**
38
+ * Convenience class: upload bytes and return a ResourceLink in one step.
39
+ *
40
+ * Usage:
41
+ * const link = await new MediaResult(pngBytes, "chart.png", "image/png").toResourceLink();
42
+ * // or use the standalone function:
43
+ * const link = await createMediaResult(pngBytes, "chart.png", "image/png");
44
+ */
45
+ export class MediaResult {
46
+ data;
47
+ filename;
48
+ mimeType;
49
+ name;
50
+ description;
51
+ constructor(data, filename, mimeType, name, description) {
52
+ this.data = data;
53
+ this.filename = filename;
54
+ this.mimeType = mimeType;
55
+ this.name = name;
56
+ this.description = description;
57
+ }
58
+ async toResourceLink() {
59
+ const uri = await uploadMedia(this.data, this.filename, this.mimeType);
60
+ return mediaResult(uri, this.name ?? this.filename, this.mimeType, this.description, this.data.length);
61
+ }
62
+ }
63
+ /**
64
+ * Upload bytes and return a ResourceLink in one step.
65
+ */
66
+ export async function createMediaResult(data, filename, mimeType, name, description) {
67
+ return new MediaResult(data, filename, mimeType, name, description).toResourceLink();
68
+ }
69
+ /**
70
+ * Save a file upload (e.g., from multer) to MediaStore and return the URI.
71
+ *
72
+ * Accepts objects with buffer/originalname/mimetype properties (multer format)
73
+ * or any object with data/name/mimeType properties.
74
+ */
75
+ export async function saveUpload(file, options) {
76
+ const data = 'buffer' in file ? file.buffer : file.data;
77
+ const filename = options?.filename ?? ('originalname' in file ? file.originalname : file.name);
78
+ const mime = options?.mimeType ?? ('mimetype' in file ? file.mimetype : file.mimeType);
79
+ const store = getMediaStore();
80
+ return store.upload(data, filename, mime);
81
+ }
82
+ /**
83
+ * Save a file upload and return full metadata.
84
+ */
85
+ export async function saveUploadResult(file, options) {
86
+ const data = 'buffer' in file ? file.buffer : file.data;
87
+ const filename = options?.filename ?? ('originalname' in file ? file.originalname : file.name);
88
+ const mime = options?.mimeType ?? ('mimetype' in file ? file.mimetype : file.mimeType);
89
+ const store = getMediaStore();
90
+ const uri = await store.upload(data, filename, mime);
91
+ return { uri, name: filename, mimeType: mime, size: data.length };
92
+ }
93
+ // ---------------------------------------------------------------------------
94
+ // resolveMediaInputs — resolve media URIs/buffers to OpenAI-compatible parts
95
+ // ---------------------------------------------------------------------------
96
+ /**
97
+ * Resolve an array of media inputs to OpenAI-compatible image_url content parts.
98
+ *
99
+ * Each item is either:
100
+ * - A URI string (resolved via MediaStore.fetch())
101
+ * - An inline `{ data: Buffer; mimeType: string }` object
102
+ *
103
+ * Returns an array of ResolvedContent parts in OpenAI image_url format,
104
+ * which Vercel AI SDK converts to each vendor's native format.
105
+ *
106
+ * @param media - Array of URI strings or inline media objects
107
+ * @returns Array of OpenAI-compatible image_url content parts
108
+ */
109
+ export async function resolveMediaInputs(media) {
110
+ const store = getMediaStore();
111
+ const parts = [];
112
+ for (const item of media) {
113
+ try {
114
+ let data;
115
+ let mimeType;
116
+ if (typeof item === "string") {
117
+ const result = await store.fetch(item);
118
+ data = result.data;
119
+ mimeType = result.mimeType;
120
+ }
121
+ else {
122
+ data = item.data;
123
+ mimeType = item.mimeType;
124
+ }
125
+ const b64 = data.toString("base64");
126
+ parts.push(formatForOpenai(b64, mimeType));
127
+ }
128
+ catch (err) {
129
+ const label = typeof item === "string" ? item : "(inline media)";
130
+ console.error(`[media] Failed to resolve ${label}, skipping:`, err);
131
+ }
132
+ }
133
+ return parts;
134
+ }
135
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * MediaStore abstraction for multimodal content storage.
3
+ *
4
+ * Provides pluggable storage backends (local filesystem, S3) for
5
+ * binary media referenced by resource_link content items.
6
+ */
7
+ /**
8
+ * Storage backend for media blobs.
9
+ */
10
+ export interface MediaStore {
11
+ /** Upload data and return a URI for later retrieval. */
12
+ upload(data: Buffer, filename: string, mimeType: string): Promise<string>;
13
+ /** Fetch previously stored data by URI. */
14
+ fetch(uri: string): Promise<{
15
+ data: Buffer;
16
+ mimeType: string;
17
+ }>;
18
+ /** Check whether a URI exists in the store. */
19
+ exists(uri: string): Promise<boolean>;
20
+ }
21
+ /** Guess MIME type from a filename extension. Falls back to application/octet-stream. */
22
+ export declare function guessMimeType(filename: string): string;
23
+ /**
24
+ * Local filesystem media store.
25
+ *
26
+ * Stores files under a configurable base path and returns `file://` URIs.
27
+ */
28
+ export declare class LocalMediaStore implements MediaStore {
29
+ private readonly basePath;
30
+ private readonly prefix;
31
+ constructor(basePath?: string, prefix?: string);
32
+ private validatePath;
33
+ upload(data: Buffer, filename: string, _mimeType: string): Promise<string>;
34
+ fetch(uri: string): Promise<{
35
+ data: Buffer;
36
+ mimeType: string;
37
+ }>;
38
+ exists(uri: string): Promise<boolean>;
39
+ }
40
+ /**
41
+ * S3-compatible media store.
42
+ *
43
+ * Uses lazy imports for @aws-sdk/client-s3 so it is only required
44
+ * when storage is configured as "s3".
45
+ */
46
+ export declare class S3MediaStore implements MediaStore {
47
+ private readonly bucket;
48
+ private readonly endpoint;
49
+ private readonly prefix;
50
+ private _client;
51
+ constructor(bucket?: string, endpoint?: string, prefix?: string);
52
+ private getClient;
53
+ private loadS3Module;
54
+ upload(data: Buffer, filename: string, mimeType: string): Promise<string>;
55
+ fetch(uri: string): Promise<{
56
+ data: Buffer;
57
+ mimeType: string;
58
+ }>;
59
+ exists(uri: string): Promise<boolean>;
60
+ private parseUri;
61
+ }
62
+ /**
63
+ * Get (or create) the singleton MediaStore based on configuration.
64
+ *
65
+ * Reads `media_storage` config key (env: `MCP_MESH_MEDIA_STORAGE`).
66
+ * - `"local"` (default) -> LocalMediaStore
67
+ * - `"s3"` -> S3MediaStore
68
+ */
69
+ export declare function getMediaStore(): MediaStore;
70
+ /**
71
+ * Reset the singleton (mainly for testing).
72
+ * @internal
73
+ */
74
+ export declare function _resetMediaStore(): void;
75
+ //# sourceMappingURL=media-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-store.d.ts","sourceRoot":"","sources":["../../src/media/media-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,wDAAwD;IACxD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE1E,2CAA2C;IAC3C,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAEhE,+CAA+C;IAC/C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvC;AAuBD,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGtD;AAED;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,UAAU;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;YAMhC,YAAY;IAQpB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAc1E,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAW/D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAY5C;AAED;;;;;GAKG;AACH,qBAAa,YAAa,YAAW,UAAU;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAIhC,OAAO,CAAC,OAAO,CAAa;gBAEhB,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;YAQjD,SAAS;YAmBT,YAAY;IAKpB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiBzE,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAkB/D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqB3C,OAAO,CAAC,QAAQ;CAejB;AAQD;;;;;;GAMG;AACH,wBAAgB,aAAa,IAAI,UAAU,CAe1C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
@@ -0,0 +1,217 @@
1
+ /**
2
+ * MediaStore abstraction for multimodal content storage.
3
+ *
4
+ * Provides pluggable storage backends (local filesystem, S3) for
5
+ * binary media referenced by resource_link content items.
6
+ */
7
+ import { resolveMediaConfig } from "../config.js";
8
+ /** Simple extension-to-MIME mapping for common types. */
9
+ const MIME_MAP = {
10
+ ".png": "image/png",
11
+ ".jpg": "image/jpeg",
12
+ ".jpeg": "image/jpeg",
13
+ ".gif": "image/gif",
14
+ ".webp": "image/webp",
15
+ ".svg": "image/svg+xml",
16
+ ".mp3": "audio/mpeg",
17
+ ".wav": "audio/wav",
18
+ ".mp4": "video/mp4",
19
+ ".webm": "video/webm",
20
+ ".pdf": "application/pdf",
21
+ ".json": "application/json",
22
+ ".txt": "text/plain",
23
+ ".html": "text/html",
24
+ ".css": "text/css",
25
+ ".csv": "text/csv",
26
+ ".md": "text/markdown",
27
+ };
28
+ /** Guess MIME type from a filename extension. Falls back to application/octet-stream. */
29
+ export function guessMimeType(filename) {
30
+ const ext = filename.slice(filename.lastIndexOf(".")).toLowerCase();
31
+ return MIME_MAP[ext] ?? "application/octet-stream";
32
+ }
33
+ /**
34
+ * Local filesystem media store.
35
+ *
36
+ * Stores files under a configurable base path and returns `file://` URIs.
37
+ */
38
+ export class LocalMediaStore {
39
+ basePath;
40
+ prefix;
41
+ constructor(basePath, prefix) {
42
+ const cfg = resolveMediaConfig();
43
+ this.basePath = basePath ?? cfg.storagePath;
44
+ this.prefix = prefix ?? cfg.storagePrefix;
45
+ }
46
+ async validatePath(filePath) {
47
+ const { resolve } = await import("node:path");
48
+ const resolved = resolve(filePath);
49
+ if (!resolved.startsWith(resolve(this.basePath))) {
50
+ throw new Error(`Invalid filename (path traversal): ${filePath}`);
51
+ }
52
+ }
53
+ async upload(data, filename, _mimeType) {
54
+ const { mkdir, writeFile } = await import("node:fs/promises");
55
+ const { join } = await import("node:path");
56
+ const dir = join(this.basePath, this.prefix);
57
+ await mkdir(dir, { recursive: true });
58
+ const filePath = join(dir, filename);
59
+ await this.validatePath(filePath);
60
+ await writeFile(filePath, data);
61
+ return `file://${filePath}`;
62
+ }
63
+ async fetch(uri) {
64
+ const { readFile } = await import("node:fs/promises");
65
+ const filePath = uri.startsWith("file://") ? uri.slice(7) : uri;
66
+ await this.validatePath(filePath);
67
+ const data = await readFile(filePath);
68
+ const mimeType = guessMimeType(filePath);
69
+ return { data: Buffer.from(data), mimeType };
70
+ }
71
+ async exists(uri) {
72
+ const { access } = await import("node:fs/promises");
73
+ const filePath = uri.startsWith("file://") ? uri.slice(7) : uri;
74
+ try {
75
+ await this.validatePath(filePath);
76
+ await access(filePath);
77
+ return true;
78
+ }
79
+ catch {
80
+ return false;
81
+ }
82
+ }
83
+ }
84
+ /**
85
+ * S3-compatible media store.
86
+ *
87
+ * Uses lazy imports for @aws-sdk/client-s3 so it is only required
88
+ * when storage is configured as "s3".
89
+ */
90
+ export class S3MediaStore {
91
+ bucket;
92
+ endpoint;
93
+ prefix;
94
+ // Lazily initialised S3 client
95
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
96
+ _client = null;
97
+ constructor(bucket, endpoint, prefix) {
98
+ const cfg = resolveMediaConfig();
99
+ this.bucket = bucket ?? cfg.storageBucket ?? "mcp-mesh-media";
100
+ this.endpoint = endpoint ?? cfg.storageEndpoint;
101
+ this.prefix = prefix ?? cfg.storagePrefix;
102
+ }
103
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
104
+ async getClient() {
105
+ if (this._client)
106
+ return this._client;
107
+ // Lazy import - @aws-sdk/client-s3 is NOT a required dependency.
108
+ // Uses variable to prevent TypeScript from resolving the module at compile time.
109
+ const s3ModuleName = "@aws-sdk/client-s3";
110
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
111
+ const s3Module = await import(/* webpackIgnore: true */ s3ModuleName);
112
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
+ const opts = {};
114
+ if (this.endpoint) {
115
+ opts.endpoint = this.endpoint;
116
+ opts.forcePathStyle = true;
117
+ }
118
+ this._client = new s3Module.S3Client(opts);
119
+ return this._client;
120
+ }
121
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
122
+ async loadS3Module() {
123
+ const name = "@aws-sdk/client-s3";
124
+ return import(/* webpackIgnore: true */ name);
125
+ }
126
+ async upload(data, filename, mimeType) {
127
+ const s3Module = await this.loadS3Module();
128
+ const client = await this.getClient();
129
+ const key = `${this.prefix}${filename}`;
130
+ await client.send(new s3Module.PutObjectCommand({
131
+ Bucket: this.bucket,
132
+ Key: key,
133
+ Body: data,
134
+ ContentType: mimeType,
135
+ }));
136
+ return `s3://${this.bucket}/${key}`;
137
+ }
138
+ async fetch(uri) {
139
+ const s3Module = await this.loadS3Module();
140
+ const client = await this.getClient();
141
+ const { bucket, key } = this.parseUri(uri);
142
+ const response = await client.send(new s3Module.GetObjectCommand({ Bucket: bucket, Key: key }));
143
+ const body = await response.Body?.transformToByteArray();
144
+ if (!body)
145
+ throw new Error(`Empty body for ${uri}`);
146
+ return {
147
+ data: Buffer.from(body),
148
+ mimeType: response.ContentType ?? guessMimeType(key),
149
+ };
150
+ }
151
+ async exists(uri) {
152
+ const s3Module = await this.loadS3Module();
153
+ const client = await this.getClient();
154
+ const { bucket, key } = this.parseUri(uri);
155
+ try {
156
+ await client.send(new s3Module.HeadObjectCommand({ Bucket: bucket, Key: key }));
157
+ return true;
158
+ }
159
+ catch (err) {
160
+ // Only treat "not found" as false; re-throw real errors
161
+ if (err instanceof Error &&
162
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
163
+ (err.name === "NotFound" || err.$metadata?.httpStatusCode === 404)) {
164
+ return false;
165
+ }
166
+ throw err;
167
+ }
168
+ }
169
+ parseUri(uri) {
170
+ if (uri.startsWith("s3://")) {
171
+ const withoutScheme = uri.slice(5);
172
+ const slashIdx = withoutScheme.indexOf("/");
173
+ if (slashIdx === -1) {
174
+ return { bucket: withoutScheme, key: "" };
175
+ }
176
+ return {
177
+ bucket: withoutScheme.slice(0, slashIdx),
178
+ key: withoutScheme.slice(slashIdx + 1),
179
+ };
180
+ }
181
+ // Assume key-only, use configured bucket
182
+ return { bucket: this.bucket, key: uri };
183
+ }
184
+ }
185
+ // ---------------------------------------------------------------------------
186
+ // Singleton factory
187
+ // ---------------------------------------------------------------------------
188
+ let _instance = null;
189
+ /**
190
+ * Get (or create) the singleton MediaStore based on configuration.
191
+ *
192
+ * Reads `media_storage` config key (env: `MCP_MESH_MEDIA_STORAGE`).
193
+ * - `"local"` (default) -> LocalMediaStore
194
+ * - `"s3"` -> S3MediaStore
195
+ */
196
+ export function getMediaStore() {
197
+ if (_instance)
198
+ return _instance;
199
+ const cfg = resolveMediaConfig();
200
+ switch (cfg.storage) {
201
+ case "s3":
202
+ _instance = new S3MediaStore();
203
+ break;
204
+ default:
205
+ _instance = new LocalMediaStore();
206
+ break;
207
+ }
208
+ return _instance;
209
+ }
210
+ /**
211
+ * Reset the singleton (mainly for testing).
212
+ * @internal
213
+ */
214
+ export function _resetMediaStore() {
215
+ _instance = null;
216
+ }
217
+ //# sourceMappingURL=media-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-store.js","sourceRoot":"","sources":["../../src/media/media-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Resolve resource_link URIs to provider-native multimodal content.
3
+ *
4
+ * When an LLM provider calls a tool that returns a resource_link (e.g., an image URI),
5
+ * the LLM currently sees just a JSON string. This module resolves the URI to base64
6
+ * media in provider-native format so the LLM can actually "see" the image.
7
+ *
8
+ * Based on Python's resolver:
9
+ * src/runtime/python/_mcp_mesh/media/resolver.py
10
+ */
11
+ export interface ResolvedContent {
12
+ type: string;
13
+ [key: string]: unknown;
14
+ }
15
+ export declare function formatForOpenai(b64: string, mimeType: string): ResolvedContent;
16
+ /**
17
+ * Scan tool result for resource_link items and resolve to provider-native format.
18
+ *
19
+ * Returns a list of content parts for the LLM message.
20
+ * - For image resource_links: fetches bytes, base64 encodes, formats per vendor
21
+ * - For non-image or non-resource_link: wraps in text content
22
+ *
23
+ * @param toolResult - The raw tool result (could be object, string, etc.)
24
+ * @param vendor - One of "anthropic", "openai", "gemini", "google"
25
+ * @returns List of content dicts suitable for provider-specific message content arrays
26
+ */
27
+ export declare function resolveResourceLinks(toolResult: unknown, vendor: string): Promise<ResolvedContent[]>;
28
+ /** Vendors that do NOT support images in tool/function result messages. */
29
+ export declare const TOOL_IMAGE_UNSUPPORTED_VENDORS: Set<string>;
30
+ /**
31
+ * Resolve resource_links for inclusion in a tool result message.
32
+ *
33
+ * For vendors that support images in tool messages (Anthropic/Claude),
34
+ * returns the full multimodal content (text + image parts).
35
+ *
36
+ * For vendors that do NOT support images in tool messages (OpenAI, Gemini),
37
+ * returns text-only content with descriptive placeholders. The actual image
38
+ * should be injected via a separate user message using
39
+ * `resolveMediaAsUserMessage()`.
40
+ *
41
+ * @param toolResult - Raw tool result
42
+ * @param vendor - e.g. "anthropic", "openai", "gemini"
43
+ * @returns Content parts suitable for a tool result message
44
+ */
45
+ export declare function resolveResourceLinksForToolMessage(toolResult: unknown, vendor: string): Promise<ResolvedContent[]>;
46
+ /**
47
+ * Return a user message containing resolved images from a tool result.
48
+ *
49
+ * For vendors that do NOT support images in tool messages (OpenAI, Gemini),
50
+ * resolves resource_link items and packages the image parts into a
51
+ * `role: "user"` message that can be appended after the tool result message.
52
+ *
53
+ * For vendors that support images in tool messages (Anthropic), returns null.
54
+ *
55
+ * @param toolResult - Raw tool result
56
+ * @param vendor - e.g. "anthropic", "openai", "gemini"
57
+ * @returns A user message object with image content, or null
58
+ */
59
+ export declare function resolveMediaAsUserMessage(toolResult: unknown, vendor: string): Promise<Record<string, unknown> | null>;
60
+ /**
61
+ * Quick check whether a tool result contains any resource_link items.
62
+ *
63
+ * This is a lightweight synchronous check used to decide whether the
64
+ * more expensive async resolution is needed.
65
+ */
66
+ export declare function hasResourceLink(toolResult: unknown): boolean;
67
+ //# sourceMappingURL=resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/media/resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAsBH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAaD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAQ9E;AAwID;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,EAAE,CAAC,CA+D5B;AAED,2EAA2E;AAC3E,eAAO,MAAM,8BAA8B,aAA0C,CAAC;AAEtF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kCAAkC,CACtD,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,EAAE,CAAC,CAY5B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAoBzC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAoB5D"}