@attrove/mcp 0.1.6 → 0.1.8

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 (47) hide show
  1. package/README.md +101 -3
  2. package/cjs/index.js +6 -1
  3. package/cjs/server.js +115 -56
  4. package/cjs/tools/events.js +134 -0
  5. package/cjs/tools/index.js +9 -1
  6. package/cjs/tools/integrations.js +11 -4
  7. package/cjs/tools/meetings.js +149 -0
  8. package/cjs/tools/query.js +12 -5
  9. package/cjs/tools/search.js +21 -7
  10. package/cjs/transport/http.js +192 -0
  11. package/esm/index.d.ts +3 -1
  12. package/esm/index.d.ts.map +1 -1
  13. package/esm/index.js +3 -1
  14. package/esm/index.js.map +1 -1
  15. package/esm/server.d.ts +7 -5
  16. package/esm/server.d.ts.map +1 -1
  17. package/esm/server.js +116 -57
  18. package/esm/server.js.map +1 -1
  19. package/esm/tools/events.d.ts +24 -0
  20. package/esm/tools/events.d.ts.map +1 -0
  21. package/esm/tools/events.js +131 -0
  22. package/esm/tools/events.js.map +1 -0
  23. package/esm/tools/index.d.ts +6 -69
  24. package/esm/tools/index.d.ts.map +1 -1
  25. package/esm/tools/index.js +5 -2
  26. package/esm/tools/index.js.map +1 -1
  27. package/esm/tools/integrations.d.ts +3 -10
  28. package/esm/tools/integrations.d.ts.map +1 -1
  29. package/esm/tools/integrations.js +11 -4
  30. package/esm/tools/integrations.js.map +1 -1
  31. package/esm/tools/meetings.d.ts +26 -0
  32. package/esm/tools/meetings.d.ts.map +1 -0
  33. package/esm/tools/meetings.js +146 -0
  34. package/esm/tools/meetings.js.map +1 -0
  35. package/esm/tools/query.d.ts +3 -27
  36. package/esm/tools/query.d.ts.map +1 -1
  37. package/esm/tools/query.js +12 -5
  38. package/esm/tools/query.js.map +1 -1
  39. package/esm/tools/search.d.ts +3 -35
  40. package/esm/tools/search.d.ts.map +1 -1
  41. package/esm/tools/search.js +21 -7
  42. package/esm/tools/search.js.map +1 -1
  43. package/esm/transport/http.d.ts +63 -0
  44. package/esm/transport/http.d.ts.map +1 -0
  45. package/esm/transport/http.js +189 -0
  46. package/esm/transport/http.js.map +1 -0
  47. package/package.json +2 -2
@@ -0,0 +1,189 @@
1
+ /**
2
+ * HTTP Transport for Attrove MCP Server
3
+ *
4
+ * Provides HTTP-based transport for the MCP server, enabling AI assistants
5
+ * like ChatGPT to connect via HTTP endpoints instead of stdio.
6
+ */
7
+ import { randomUUID } from "node:crypto";
8
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
9
+ import { createServer } from "../server.js";
10
+ /**
11
+ * Create an HTTP request handler for the MCP server.
12
+ *
13
+ * Each call to handleRequest creates new server and transport instances,
14
+ * providing complete isolation between requests. Callers should create
15
+ * a new handler when the config (API key/user ID) changes.
16
+ *
17
+ * @param config - MCP server configuration with API key and user ID
18
+ * @param options - Optional handler configuration
19
+ * @returns Object with handleRequest method for processing HTTP requests
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // In a Fastify route handler
24
+ * const handler = createHttpHandler({
25
+ * apiKey: 'sk_...',
26
+ * userId: 'user-uuid',
27
+ * baseUrl: 'https://api.attrove.com', // optional, SDK has its own default
28
+ * });
29
+ *
30
+ * // Handle POST request
31
+ * const result = await handler.handleRequest(req.raw, reply.raw, req.body);
32
+ * if (!result.handled) {
33
+ * // No response sent - caller must send error response
34
+ * res.status(500).json({ error: result.error });
35
+ * }
36
+ * ```
37
+ */
38
+ /**
39
+ * Type guard for Node.js system errors with error codes.
40
+ */
41
+ function isNodeError(error) {
42
+ return error instanceof Error && "code" in error;
43
+ }
44
+ export function createHttpHandler(config, options = {}) {
45
+ const { enableJsonResponse = true, timeoutMs = 30000 } = options;
46
+ // Validate timeoutMs to prevent unexpected behavior
47
+ if (timeoutMs <= 0) {
48
+ throw new Error("timeoutMs must be a positive number");
49
+ }
50
+ return {
51
+ /**
52
+ * Handle an incoming HTTP request.
53
+ *
54
+ * @param req - Node.js IncomingMessage (or Fastify raw request)
55
+ * @param res - Node.js ServerResponse (or Fastify raw reply)
56
+ * @param parsedBody - Pre-parsed request body (optional, Fastify provides this)
57
+ * @returns Promise resolving to handler result indicating if request was processed
58
+ */
59
+ handleRequest: async (req, res, parsedBody) => {
60
+ let server;
61
+ let timeoutId;
62
+ let result;
63
+ let cleanupFailed = false;
64
+ let timeoutOccurred = false;
65
+ // Correlation ID links timeout errors with subsequent suppressed errors for debugging
66
+ const correlationId = randomUUID().slice(0, 8);
67
+ try {
68
+ server = createServer(config);
69
+ const transport = new StreamableHTTPServerTransport({
70
+ sessionIdGenerator: undefined, // Stateless mode - no session tracking needed
71
+ enableJsonResponse,
72
+ });
73
+ await server.connect(transport);
74
+ const timeoutPromise = new Promise((_, reject) => {
75
+ timeoutId = setTimeout(() => {
76
+ timeoutOccurred = true;
77
+ reject(new Error(`MCP request timed out after ${timeoutMs}ms`));
78
+ }, timeoutMs);
79
+ });
80
+ // Store reference to transport promise so we can attach a catch handler.
81
+ // This prevents unhandled rejection if timeout wins the race and server.close()
82
+ // later causes the transport to reject.
83
+ const transportPromise = transport.handleRequest(req, res, parsedBody);
84
+ // When timeout occurs, Promise.race exits with the timeout error (caught below),
85
+ // but transportPromise may reject later when server.close() interrupts it.
86
+ // Only log here if a timeout actually occurred - otherwise Promise.race will
87
+ // propagate the rejection to the main catch block and logging here would be duplicate.
88
+ transportPromise.catch((suppressedError) => {
89
+ if (!timeoutOccurred) {
90
+ // No timeout - Promise.race will handle this rejection via the main catch block
91
+ return;
92
+ }
93
+ const errorMsg = suppressedError instanceof Error
94
+ ? suppressedError.message
95
+ : String(suppressedError);
96
+ // Critical errors that indicate systemic issues (not just slow requests)
97
+ const isCritical = /SSL|certificate|ENOTFOUND|ECONNREFUSED|auth/i.test(errorMsg);
98
+ const logData = {
99
+ level: isCritical ? "error" : "warn",
100
+ msg: "MCP transport rejected after timeout - suppressed to prevent unhandled rejection",
101
+ errorId: isCritical
102
+ ? "MCP_HTTP_SUPPRESSED_CRITICAL_ERROR"
103
+ : "MCP_HTTP_SUPPRESSED_POST_TIMEOUT",
104
+ correlationId,
105
+ error: errorMsg,
106
+ userId: config.userId,
107
+ };
108
+ // prettier-ignore
109
+ console.error("[AttroveMCP]", JSON.stringify(logData));
110
+ });
111
+ await Promise.race([transportPromise, timeoutPromise]);
112
+ result = { handled: true };
113
+ }
114
+ catch (error) {
115
+ // Preserve context for non-Error values (e.g., throw "string", throw { code: ... })
116
+ const message = error instanceof Error
117
+ ? error.message
118
+ : typeof error === "object" && error !== null
119
+ ? `Unknown error: ${JSON.stringify(error)}`
120
+ : `Unknown error: ${String(error)}`;
121
+ const stack = error instanceof Error ? error.stack : undefined;
122
+ const isTimeout = error instanceof Error && error.message.includes("timed out");
123
+ // Classify error type for appropriate logging level
124
+ // Use error.code for socket errors (more precise than string matching)
125
+ const isSocketError = isNodeError(error) &&
126
+ (error.code === "ECONNRESET" ||
127
+ error.code === "EPIPE" ||
128
+ error.code === "ECONNABORTED");
129
+ const isExpectedError = isTimeout || isSocketError;
130
+ // Log with structured JSON for observability (callers should also log via their infrastructure)
131
+ const errorId = isTimeout
132
+ ? "MCP_HTTP_TIMEOUT"
133
+ : isSocketError
134
+ ? "MCP_HTTP_SOCKET_ERROR"
135
+ : "MCP_HTTP_UNEXPECTED_ERROR";
136
+ const logData = {
137
+ level: isExpectedError ? "warn" : "error",
138
+ msg: isExpectedError
139
+ ? "MCP HTTP handler operational failure"
140
+ : "MCP HTTP handler unexpected failure",
141
+ errorId,
142
+ correlationId,
143
+ error: message,
144
+ isTimeout,
145
+ userId: config.userId,
146
+ ...(stack && !isExpectedError && { stack }),
147
+ ...(!isExpectedError && { errorType: error?.constructor?.name }),
148
+ };
149
+ // prettier-ignore
150
+ console.error("[AttroveMCP]", JSON.stringify(logData));
151
+ result = { handled: false, error: message, stack, isTimeout };
152
+ }
153
+ finally {
154
+ // Clear timeout to prevent timer accumulation under load
155
+ if (timeoutId !== undefined) {
156
+ clearTimeout(timeoutId);
157
+ }
158
+ if (server) {
159
+ try {
160
+ await server.close();
161
+ }
162
+ catch (cleanupError) {
163
+ cleanupFailed = true;
164
+ // Cleanup failures could indicate resource leaks - always log for monitoring
165
+ const cleanupLogData = {
166
+ level: "error",
167
+ msg: "MCP server cleanup failed - potential resource leak",
168
+ errorId: "MCP_CLEANUP_FAILURE",
169
+ correlationId,
170
+ error: cleanupError instanceof Error
171
+ ? cleanupError.message
172
+ : String(cleanupError),
173
+ stack: cleanupError instanceof Error ? cleanupError.stack : undefined,
174
+ userId: config.userId,
175
+ };
176
+ // prettier-ignore
177
+ console.error("[AttroveMCP]", JSON.stringify(cleanupLogData));
178
+ }
179
+ }
180
+ }
181
+ // Include cleanup failure warning in success result for monitoring
182
+ if (result.handled && cleanupFailed) {
183
+ return { handled: true, cleanupFailed: true };
184
+ }
185
+ return result;
186
+ },
187
+ };
188
+ }
189
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../../../packages/mcp/src/transport/http.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@attrove/mcp",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "MCP server for Attrove - AI-powered context retrieval for Claude and Cursor",
5
5
  "type": "module",
6
6
  "main": "./cjs/index.js",
@@ -58,7 +58,7 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "@modelcontextprotocol/sdk": "^1.0.0",
61
- "@attrove/sdk": "0.1.6",
61
+ "@attrove/sdk": "0.1.8",
62
62
  "tslib": "^2.6.0"
63
63
  },
64
64
  "devDependencies": {