@nanogpt/mcp 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 (57) hide show
  1. package/dist/activeRequests.d.ts +26 -0
  2. package/dist/activeRequests.d.ts.map +1 -0
  3. package/dist/activeRequests.js +39 -0
  4. package/dist/activeRequests.js.map +1 -0
  5. package/dist/config.d.ts +35 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +136 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/httpClient.d.ts +36 -0
  10. package/dist/httpClient.d.ts.map +1 -0
  11. package/dist/httpClient.js +211 -0
  12. package/dist/httpClient.js.map +1 -0
  13. package/dist/index.d.ts +18 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +168 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/resources.d.ts +68 -0
  18. package/dist/resources.d.ts.map +1 -0
  19. package/dist/resources.js +198 -0
  20. package/dist/resources.js.map +1 -0
  21. package/dist/toolUtils.d.ts +115 -0
  22. package/dist/toolUtils.d.ts.map +1 -0
  23. package/dist/toolUtils.js +369 -0
  24. package/dist/toolUtils.js.map +1 -0
  25. package/dist/tools/balance.d.ts +48 -0
  26. package/dist/tools/balance.d.ts.map +1 -0
  27. package/dist/tools/balance.js +78 -0
  28. package/dist/tools/balance.js.map +1 -0
  29. package/dist/tools/chat.d.ts +89 -0
  30. package/dist/tools/chat.d.ts.map +1 -0
  31. package/dist/tools/chat.js +125 -0
  32. package/dist/tools/chat.js.map +1 -0
  33. package/dist/tools/imageGenerate.d.ts +116 -0
  34. package/dist/tools/imageGenerate.d.ts.map +1 -0
  35. package/dist/tools/imageGenerate.js +220 -0
  36. package/dist/tools/imageGenerate.js.map +1 -0
  37. package/dist/tools/index.d.ts +11 -0
  38. package/dist/tools/index.d.ts.map +1 -0
  39. package/dist/tools/index.js +11 -0
  40. package/dist/tools/index.js.map +1 -0
  41. package/dist/tools/listModels.d.ts +149 -0
  42. package/dist/tools/listModels.d.ts.map +1 -0
  43. package/dist/tools/listModels.js +224 -0
  44. package/dist/tools/listModels.js.map +1 -0
  45. package/dist/tools/scrapeUrls.d.ts +51 -0
  46. package/dist/tools/scrapeUrls.d.ts.map +1 -0
  47. package/dist/tools/scrapeUrls.js +100 -0
  48. package/dist/tools/scrapeUrls.js.map +1 -0
  49. package/dist/tools/webSearch.d.ts +69 -0
  50. package/dist/tools/webSearch.d.ts.map +1 -0
  51. package/dist/tools/webSearch.js +120 -0
  52. package/dist/tools/webSearch.js.map +1 -0
  53. package/dist/tools/youtubeTranscribe.d.ts +45 -0
  54. package/dist/tools/youtubeTranscribe.d.ts.map +1 -0
  55. package/dist/tools/youtubeTranscribe.js +88 -0
  56. package/dist/tools/youtubeTranscribe.js.map +1 -0
  57. package/package.json +48 -0
package/dist/index.js ADDED
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * NanoGPT MCP Server
4
+ *
5
+ * An MCP server that provides access to NanoGPT's API capabilities:
6
+ * - Chat completion
7
+ * - Image generation
8
+ * - Web search
9
+ * - URL scraping
10
+ * - YouTube transcription
11
+ * - Model listing
12
+ *
13
+ * Uses stdio transport for communication with MCP clients.
14
+ *
15
+ * Pinned MCP SDK version: @modelcontextprotocol/sdk@^1.23.0
16
+ */
17
+ import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
18
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
19
+ import { loadConfig, log } from './config.js';
20
+ import { read, clearCache } from './resources.js';
21
+ import { abortAllRequests, getActiveRequestCount } from './activeRequests.js';
22
+ import { balance, chat, imageGenerate, webSearch, scrapeUrls, youtubeTranscribe, listTextModels, listImageModels, listAudioModels, listVideoModels, } from './tools/index.js';
23
+ /**
24
+ * Main entry point
25
+ */
26
+ async function main() {
27
+ // Load and validate configuration
28
+ const config = loadConfig();
29
+ log('info', 'NanoGPT MCP server starting', { baseUrl: config.baseUrl });
30
+ // Create MCP server
31
+ const server = new McpServer({
32
+ name: 'nanogpt-mcp',
33
+ version: '1.0.0',
34
+ });
35
+ // Register tools
36
+ registerTools(server);
37
+ // Register resource handlers
38
+ registerResources(server);
39
+ // Setup graceful shutdown
40
+ setupShutdown();
41
+ // Connect via stdio transport
42
+ const transport = new StdioServerTransport();
43
+ await server.connect(transport);
44
+ log('info', 'NanoGPT MCP server connected and ready');
45
+ }
46
+ /**
47
+ * Register all tools with the MCP server
48
+ */
49
+ function registerTools(server) {
50
+ const tools = [
51
+ balance,
52
+ chat,
53
+ imageGenerate,
54
+ webSearch,
55
+ scrapeUrls,
56
+ youtubeTranscribe,
57
+ listTextModels,
58
+ listImageModels,
59
+ listAudioModels,
60
+ listVideoModels,
61
+ ];
62
+ for (const tool of tools) {
63
+ server.registerTool(tool.name, {
64
+ description: tool.description,
65
+ // MCP SDK v1.23+ accepts Zod schemas and converts to JSON Schema internally
66
+ inputSchema: tool.inputSchema,
67
+ }, tool.handler);
68
+ }
69
+ log('info', `Registered ${tools.length} tools`);
70
+ }
71
+ /**
72
+ * Register resource handlers for reading stored resources
73
+ */
74
+ function registerResources(server) {
75
+ // Resource template for raw JSON responses
76
+ const rawTemplate = new ResourceTemplate('nanogpt://raw/{id}', { list: undefined });
77
+ server.registerResource('nanogpt-raw', rawTemplate, {
78
+ description: 'Raw JSON response from NanoGPT API',
79
+ mimeType: 'application/json',
80
+ }, async (uri, _variables) => {
81
+ const uriString = uri.toString();
82
+ const result = read(uriString);
83
+ if (!result || !result.text) {
84
+ return {
85
+ contents: [
86
+ {
87
+ uri: uriString,
88
+ mimeType: 'text/plain',
89
+ text: `Resource not found (may have been evicted): ${uriString}`,
90
+ },
91
+ ],
92
+ };
93
+ }
94
+ return {
95
+ contents: [
96
+ {
97
+ uri: uriString,
98
+ mimeType: result.mimeType,
99
+ text: result.text,
100
+ },
101
+ ],
102
+ };
103
+ });
104
+ // Resource template for stored images
105
+ const imageTemplate = new ResourceTemplate('nanogpt://image/{id}', { list: undefined });
106
+ server.registerResource('nanogpt-image', imageTemplate, {
107
+ description: 'Image generated by NanoGPT',
108
+ mimeType: 'image/*',
109
+ }, async (uri, _variables) => {
110
+ const uriString = uri.toString();
111
+ const result = read(uriString);
112
+ if (!result || !result.blob) {
113
+ return {
114
+ contents: [
115
+ {
116
+ uri: uriString,
117
+ mimeType: 'text/plain',
118
+ text: `Resource not found (may have been evicted): ${uriString}`,
119
+ },
120
+ ],
121
+ };
122
+ }
123
+ return {
124
+ contents: [
125
+ {
126
+ uri: uriString,
127
+ mimeType: result.mimeType,
128
+ blob: result.blob,
129
+ },
130
+ ],
131
+ };
132
+ });
133
+ log('info', 'Registered resource handlers for nanogpt://raw/* and nanogpt://image/*');
134
+ }
135
+ /**
136
+ * Setup graceful shutdown handlers
137
+ */
138
+ function setupShutdown() {
139
+ const shutdown = async (signal) => {
140
+ const activeCount = getActiveRequestCount();
141
+ log('info', `Received ${signal}, shutting down...`, { activeRequests: activeCount });
142
+ // Abort all active HTTP requests
143
+ abortAllRequests();
144
+ // Clear resource cache
145
+ clearCache();
146
+ log('info', 'Shutdown complete');
147
+ process.exit(0);
148
+ };
149
+ process.on('SIGINT', () => shutdown('SIGINT'));
150
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
151
+ // Handle uncaught errors
152
+ process.on('uncaughtException', (err) => {
153
+ log('error', 'Uncaught exception', { error: err.message });
154
+ process.exit(1);
155
+ });
156
+ process.on('unhandledRejection', (reason) => {
157
+ log('error', 'Unhandled rejection', {
158
+ error: reason instanceof Error ? reason.message : String(reason),
159
+ });
160
+ process.exit(1);
161
+ });
162
+ }
163
+ // Run the server
164
+ main().catch((err) => {
165
+ console.error('Fatal error:', err);
166
+ process.exit(1);
167
+ });
168
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AACtF,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,OAAO,EACP,IAAI,EACJ,aAAa,EACb,SAAS,EACT,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAE1B;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,kCAAkC;IAClC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,GAAG,CAAC,MAAM,EAAE,6BAA6B,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAExE,oBAAoB;IACpB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,iBAAiB;IACjB,aAAa,CAAC,MAAM,CAAC,CAAC;IAEtB,6BAA6B;IAC7B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE1B,0BAA0B;IAC1B,aAAa,EAAE,CAAC;IAEhB,8BAA8B;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,GAAG,CAAC,MAAM,EAAE,wCAAwC,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,MAAiB;IACtC,MAAM,KAAK,GAAG;QACZ,OAAO;QACP,IAAI;QACJ,aAAa;QACb,SAAS;QACT,UAAU;QACV,iBAAiB;QACjB,cAAc;QACd,eAAe;QACf,eAAe;QACf,eAAe;KAChB,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,YAAY,CACjB,IAAI,CAAC,IAAI,EACT;YACE,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,4EAA4E;YAC5E,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,EACD,IAAI,CAAC,OAAoD,CAC1D,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,MAAM,EAAE,cAAc,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,MAAiB;IAG1C,2CAA2C;IAC3C,MAAM,WAAW,GAAG,IAAI,gBAAgB,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACpF,MAAM,CAAC,gBAAgB,CACrB,aAAa,EACb,WAAW,EACX;QACE,WAAW,EAAE,oCAAoC;QACjD,QAAQ,EAAE,kBAAkB;KAC7B,EACL,KAAK,EAAE,GAAQ,EAAE,UAAqB,EAAE,EAAE;QACpC,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;QAE/B,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5B,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,SAAS;wBACd,QAAQ,EAAE,YAAY;wBACtB,IAAI,EAAE,+CAA+C,SAAS,EAAE;qBACjE;iBACF;aACF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,SAAS;oBACd,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,IAAI,EAAE,MAAM,CAAC,IAAI;iBAClB;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,sCAAsC;IACtC,MAAM,aAAa,GAAG,IAAI,gBAAgB,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACxF,MAAM,CAAC,gBAAgB,CACrB,eAAe,EACf,aAAa,EACb;QACE,WAAW,EAAE,4BAA4B;QACzC,QAAQ,EAAE,SAAS;KACpB,EACL,KAAK,EAAE,GAAQ,EAAE,UAAqB,EAAE,EAAE;QACpC,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;QAE/B,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5B,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,SAAS;wBACd,QAAQ,EAAE,YAAY;wBACtB,IAAI,EAAE,+CAA+C,SAAS,EAAE;qBACjE;iBACF;aACF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,SAAS;oBACd,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,IAAI,EAAE,MAAM,CAAC,IAAI;iBAClB;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,GAAG,CAAC,MAAM,EAAE,wEAAwE,CAAC,CAAC;AACxF,CAAC;AAED;;GAEG;AACH,SAAS,aAAa;IACpB,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;QACxC,MAAM,WAAW,GAAG,qBAAqB,EAAE,CAAC;QAC5C,GAAG,CAAC,MAAM,EAAE,YAAY,MAAM,oBAAoB,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;QAErF,iCAAiC;QACjC,gBAAgB,EAAE,CAAC;QAEnB,uBAAuB;QACvB,UAAU,EAAE,CAAC;QAEb,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IAEjD,yBAAyB;IACzB,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,EAAE;QACtC,GAAG,CAAC,OAAO,EAAE,oBAAoB,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,EAAE;QAC1C,GAAG,CAAC,OAAO,EAAE,qBAAqB,EAAE;YAClC,KAAK,EAAE,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;SACjE,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,iBAAiB;AACjB,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * In-memory LRU resource cache for NanoGPT MCP server
3
+ *
4
+ * Stores large payloads (images, raw JSON) that are too big to inline.
5
+ * Resources are ephemeral and will be evicted when the cache is full.
6
+ */
7
+ export type ResourceType = 'raw' | 'image';
8
+ /**
9
+ * Generate a resource URI
10
+ */
11
+ export declare function makeUri(type: ResourceType, id: string): string;
12
+ /**
13
+ * Parse a resource URI
14
+ */
15
+ export declare function parseUri(uri: string): {
16
+ type: ResourceType;
17
+ id: string;
18
+ } | null;
19
+ /**
20
+ * Store raw text/JSON as a resource
21
+ */
22
+ export declare function putRawText(text: string, mimeType?: string): {
23
+ uri: string;
24
+ bytes: number;
25
+ } | null;
26
+ /**
27
+ * Store binary data (image) as a resource
28
+ */
29
+ export declare function putBlob(buffer: Buffer, mimeType: string): {
30
+ uri: string;
31
+ bytes: number;
32
+ } | null;
33
+ /**
34
+ * Store base64-encoded image data
35
+ */
36
+ export declare function putBase64Image(base64: string, mimeType: string): {
37
+ uri: string;
38
+ bytes: number;
39
+ } | null;
40
+ export interface ResourceReadResult {
41
+ mimeType: string;
42
+ text?: string;
43
+ blob?: string;
44
+ }
45
+ /**
46
+ * Read a resource by URI
47
+ */
48
+ export declare function read(uri: string): ResourceReadResult | null;
49
+ /**
50
+ * List all cached resources (for resources/list)
51
+ */
52
+ export declare function listResources(): Array<{
53
+ uri: string;
54
+ name: string;
55
+ mimeType: string;
56
+ }>;
57
+ /**
58
+ * Clear all cached resources (for graceful shutdown)
59
+ */
60
+ export declare function clearCache(): void;
61
+ /**
62
+ * Get cache statistics (for debugging)
63
+ */
64
+ export declare function getCacheStats(): {
65
+ count: number;
66
+ totalBytes: number;
67
+ };
68
+ //# sourceMappingURL=resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,OAAO,CAAC;AAe3C;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAO/E;AAwBD;;GAEG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAA2B,GACpC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA6BvC;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAiC/F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAgCvC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAqB3D;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAYtF;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAGjC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CASrE"}
@@ -0,0 +1,198 @@
1
+ /**
2
+ * In-memory LRU resource cache for NanoGPT MCP server
3
+ *
4
+ * Stores large payloads (images, raw JSON) that are too big to inline.
5
+ * Resources are ephemeral and will be evicted when the cache is full.
6
+ */
7
+ import { randomUUID } from 'crypto';
8
+ import { getConfig } from './config.js';
9
+ // In-memory LRU cache
10
+ const cache = new Map();
11
+ const accessOrder = [];
12
+ /**
13
+ * Generate a resource URI
14
+ */
15
+ export function makeUri(type, id) {
16
+ return `nanogpt://${type}/${id}`;
17
+ }
18
+ /**
19
+ * Parse a resource URI
20
+ */
21
+ export function parseUri(uri) {
22
+ const match = uri.match(/^nanogpt:\/\/(raw|image)\/([a-f0-9-]+)$/);
23
+ if (!match)
24
+ return null;
25
+ return {
26
+ type: match[1],
27
+ id: match[2],
28
+ };
29
+ }
30
+ /**
31
+ * Update access order for LRU eviction
32
+ */
33
+ function updateAccessOrder(id) {
34
+ const index = accessOrder.indexOf(id);
35
+ if (index > -1) {
36
+ accessOrder.splice(index, 1);
37
+ }
38
+ accessOrder.push(id);
39
+ }
40
+ /**
41
+ * Evict oldest entries if cache is full
42
+ */
43
+ function evictIfNeeded() {
44
+ const config = getConfig();
45
+ while (cache.size >= config.maxResourceCacheItems && accessOrder.length > 0) {
46
+ const oldestId = accessOrder.shift();
47
+ cache.delete(oldestId);
48
+ }
49
+ }
50
+ /**
51
+ * Store raw text/JSON as a resource
52
+ */
53
+ export function putRawText(text, mimeType = 'application/json') {
54
+ const config = getConfig();
55
+ const bytes = Buffer.byteLength(text, 'utf-8');
56
+ // Check size limit
57
+ if (bytes > config.maxResourceBytes) {
58
+ return null;
59
+ }
60
+ // Evict if needed
61
+ evictIfNeeded();
62
+ const id = randomUUID();
63
+ const entry = {
64
+ id,
65
+ type: 'raw',
66
+ mimeType,
67
+ data: text,
68
+ bytes,
69
+ createdAt: Date.now(),
70
+ };
71
+ cache.set(id, entry);
72
+ updateAccessOrder(id);
73
+ return {
74
+ uri: makeUri('raw', id),
75
+ bytes,
76
+ };
77
+ }
78
+ /**
79
+ * Store binary data (image) as a resource
80
+ */
81
+ export function putBlob(buffer, mimeType) {
82
+ const config = getConfig();
83
+ // Convert to base64 first, then check size limit against actual stored size
84
+ // (base64 encoding expands data by ~33%)
85
+ const base64Data = buffer.toString('base64');
86
+ const storedBytes = base64Data.length;
87
+ // Check size limit against actual stored size
88
+ if (storedBytes > config.maxResourceBytes) {
89
+ return null;
90
+ }
91
+ // Evict if needed
92
+ evictIfNeeded();
93
+ const id = randomUUID();
94
+ const entry = {
95
+ id,
96
+ type: 'image',
97
+ mimeType,
98
+ data: base64Data,
99
+ bytes: storedBytes,
100
+ createdAt: Date.now(),
101
+ };
102
+ cache.set(id, entry);
103
+ updateAccessOrder(id);
104
+ return {
105
+ uri: makeUri('image', id),
106
+ bytes: storedBytes,
107
+ };
108
+ }
109
+ /**
110
+ * Store base64-encoded image data
111
+ */
112
+ export function putBase64Image(base64, mimeType) {
113
+ const config = getConfig();
114
+ // Remove data URL prefix if present
115
+ const cleanBase64 = base64.replace(/^data:[^,]+,/, '');
116
+ const bytes = cleanBase64.length; // Track actual stored string size
117
+ // Check size limit
118
+ if (bytes > config.maxResourceBytes) {
119
+ return null;
120
+ }
121
+ // Evict if needed
122
+ evictIfNeeded();
123
+ const id = randomUUID();
124
+ const entry = {
125
+ id,
126
+ type: 'image',
127
+ mimeType,
128
+ data: cleanBase64,
129
+ bytes,
130
+ createdAt: Date.now(),
131
+ };
132
+ cache.set(id, entry);
133
+ updateAccessOrder(id);
134
+ return {
135
+ uri: makeUri('image', id),
136
+ bytes,
137
+ };
138
+ }
139
+ /**
140
+ * Read a resource by URI
141
+ */
142
+ export function read(uri) {
143
+ const parsed = parseUri(uri);
144
+ if (!parsed)
145
+ return null;
146
+ const entry = cache.get(parsed.id);
147
+ if (!entry)
148
+ return null;
149
+ // Update access order
150
+ updateAccessOrder(parsed.id);
151
+ if (entry.type === 'raw') {
152
+ return {
153
+ mimeType: entry.mimeType,
154
+ text: entry.data,
155
+ };
156
+ }
157
+ else {
158
+ return {
159
+ mimeType: entry.mimeType,
160
+ blob: entry.data,
161
+ };
162
+ }
163
+ }
164
+ /**
165
+ * List all cached resources (for resources/list)
166
+ */
167
+ export function listResources() {
168
+ const result = [];
169
+ for (const [id, entry] of cache.entries()) {
170
+ result.push({
171
+ uri: makeUri(entry.type, id),
172
+ name: entry.type === 'raw' ? 'Raw response' : 'Generated image',
173
+ mimeType: entry.mimeType,
174
+ });
175
+ }
176
+ return result;
177
+ }
178
+ /**
179
+ * Clear all cached resources (for graceful shutdown)
180
+ */
181
+ export function clearCache() {
182
+ cache.clear();
183
+ accessOrder.length = 0;
184
+ }
185
+ /**
186
+ * Get cache statistics (for debugging)
187
+ */
188
+ export function getCacheStats() {
189
+ let totalBytes = 0;
190
+ for (const entry of cache.values()) {
191
+ totalBytes += entry.bytes;
192
+ }
193
+ return {
194
+ count: cache.size,
195
+ totalBytes,
196
+ };
197
+ }
198
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Common utilities for tool handlers
3
+ *
4
+ * WARNING: The zodTypeToJsonSchema function accesses Zod internal structures (_def)
5
+ * which are not part of Zod's public API and may break with Zod updates.
6
+ * Consider switching to a maintained converter like 'zod-to-json-schema' package
7
+ * for production use with full Zod type coverage.
8
+ */
9
+ import { z, type ZodTypeAny } from 'zod';
10
+ import { McpError } from '@modelcontextprotocol/sdk/types.js';
11
+ import { type HttpError } from './httpClient.js';
12
+ export interface ResourceLink {
13
+ type: 'resource_link';
14
+ uri: string;
15
+ name: string;
16
+ mimeType: string;
17
+ }
18
+ export interface TextContent {
19
+ type: 'text';
20
+ text: string;
21
+ }
22
+ export type ContentItem = TextContent | ResourceLink;
23
+ /**
24
+ * Map HTTP error to MCP error
25
+ */
26
+ export declare function httpErrorToMcpError(err: HttpError): McpError;
27
+ /**
28
+ * Handle errors in tool handlers.
29
+ *
30
+ * This function ALWAYS throws and never returns (return type: never).
31
+ * Use as: `return handleToolError(err)` in catch blocks to make control flow
32
+ * explicit and satisfy TypeScript's type checker.
33
+ */
34
+ export declare function handleToolError(err: unknown): never;
35
+ export interface RawResponse {
36
+ status: number;
37
+ headers?: Record<string, string>;
38
+ body?: unknown;
39
+ }
40
+ /** Error returned when raw response cannot be stored */
41
+ export interface RawResponseError {
42
+ error: string;
43
+ }
44
+ /**
45
+ * Union type for the 'raw' field in processRawResponse result.
46
+ * - RawResponse: The full response object (when small enough to inline)
47
+ * - string: A URI reference to the stored resource (when stored successfully)
48
+ * - RawResponseError: An error object (when storage fails)
49
+ */
50
+ export type ProcessedRawValue = RawResponse | string | RawResponseError;
51
+ /** Result type for processRawResponse */
52
+ export interface ProcessRawResponseResult {
53
+ /** The raw response - can be inline object, URI string, or error */
54
+ raw?: ProcessedRawValue;
55
+ /** Resource link if response was stored as a resource */
56
+ resourceLink?: ResourceLink;
57
+ }
58
+ /**
59
+ * Type guard to check if raw value is an error
60
+ */
61
+ export declare function isRawResponseError(value: ProcessedRawValue): value is RawResponseError;
62
+ /**
63
+ * Type guard to check if raw value is a URI string
64
+ */
65
+ export declare function isRawResponseUri(value: ProcessedRawValue): value is string;
66
+ /**
67
+ * Type guard to check if raw value is an inline RawResponse
68
+ */
69
+ export declare function isRawResponseInline(value: ProcessedRawValue): value is RawResponse;
70
+ /**
71
+ * Process raw response - inline if small, store as resource if large
72
+ *
73
+ * @returns Object with:
74
+ * - raw: Either the inline RawResponse, a URI string to stored resource, or an error object
75
+ * - resourceLink: Present only when response was stored as a resource
76
+ */
77
+ export declare function processRawResponse(response: RawResponse, includeRaw?: boolean): ProcessRawResponseResult;
78
+ /**
79
+ * Build content array with text and optional resource link
80
+ */
81
+ export declare function buildContent(text: string, resourceLink?: ResourceLink): ContentItem[];
82
+ /**
83
+ * Common input schema for include_raw parameter
84
+ */
85
+ export declare const includeRawSchema: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
86
+ export interface JsonSchema {
87
+ type?: string | string[];
88
+ properties?: Record<string, JsonSchema>;
89
+ items?: JsonSchema;
90
+ required?: string[];
91
+ additionalProperties?: boolean;
92
+ enum?: unknown[];
93
+ const?: unknown;
94
+ oneOf?: JsonSchema[];
95
+ minimum?: number;
96
+ maximum?: number;
97
+ minLength?: number;
98
+ maxLength?: number;
99
+ minItems?: number;
100
+ maxItems?: number;
101
+ }
102
+ /**
103
+ * Zod to JSON Schema converter (simplified)
104
+ *
105
+ * WARNING: This function accesses Zod internal structures (_def) which are not
106
+ * part of Zod's public API. This implementation:
107
+ * - May break with future Zod versions
108
+ * - Does not support all Zod types (see UNSUPPORTED_ZOD_TYPES)
109
+ * - Uses defensive checks but may still fail on edge cases
110
+ *
111
+ * For production use with full Zod type coverage, consider using the
112
+ * 'zod-to-json-schema' package instead.
113
+ */
114
+ export declare function zodToJsonSchema(schema: ZodTypeAny): JsonSchema;
115
+ //# sourceMappingURL=toolUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolUtils.d.ts","sourceRoot":"","sources":["../src/toolUtils.ts"],"names":[],"mappings":"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"}