@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,149 @@
1
+ "use strict";
2
+ /**
3
+ * Meetings Tool
4
+ *
5
+ * MCP tool for listing meetings with AI-generated summaries and action items.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.executeMeetingsTool = exports.meetingsToolDefinition = void 0;
9
+ /**
10
+ * MCP schema for discovering and filtering meetings with AI-generated summaries.
11
+ */
12
+ exports.meetingsToolDefinition = {
13
+ name: "attrove_meetings",
14
+ description: `List meetings with AI-generated summaries and action items from the user's own connected accounts.
15
+
16
+ This read-only tool returns meetings from the authenticated user's authorized meeting integrations (e.g., Google Meet, Zoom, Teams) with AI-generated summaries. Only meetings from services the user has explicitly connected are accessed. Use this when the user asks about:
17
+ - "What happened in my last meeting?"
18
+ - "Summarize yesterday's standup"
19
+ - "What are the action items from the product review?"
20
+ - "Show me my recent meetings"`,
21
+ inputSchema: {
22
+ type: "object",
23
+ properties: {
24
+ start_date: {
25
+ type: "string",
26
+ description: "Start of date range (ISO 8601). If omitted, the server determines the default.",
27
+ },
28
+ end_date: {
29
+ type: "string",
30
+ description: "End of date range (ISO 8601). If omitted, the server determines the default.",
31
+ },
32
+ provider: {
33
+ type: "string",
34
+ enum: ["google_meet", "zoom", "teams"],
35
+ description: "Optional: Filter by meeting provider",
36
+ },
37
+ limit: {
38
+ type: "number",
39
+ description: "Max meetings to return (default 10, max 50)",
40
+ },
41
+ },
42
+ required: [],
43
+ },
44
+ annotations: {
45
+ title: "Meeting Summaries",
46
+ readOnlyHint: true,
47
+ destructiveHint: false,
48
+ idempotentHint: true,
49
+ openWorldHint: true,
50
+ },
51
+ };
52
+ /**
53
+ * Format a meeting's time range for display.
54
+ * Returns a fallback string when the meeting contains unparseable dates.
55
+ */
56
+ function formatMeetingTime(meeting) {
57
+ const start = new Date(meeting.start_time);
58
+ const end = new Date(meeting.end_time);
59
+ if (Number.isNaN(start.getTime()) || Number.isNaN(end.getTime())) {
60
+ return meeting.start_time ?? "Unknown time";
61
+ }
62
+ const dateStr = start.toLocaleDateString(undefined, {
63
+ weekday: "short",
64
+ month: "short",
65
+ day: "numeric",
66
+ });
67
+ const startTime = start.toLocaleTimeString(undefined, {
68
+ hour: "numeric",
69
+ minute: "2-digit",
70
+ });
71
+ const endTime = end.toLocaleTimeString(undefined, {
72
+ hour: "numeric",
73
+ minute: "2-digit",
74
+ });
75
+ return `${dateStr}, ${startTime} – ${endTime}`;
76
+ }
77
+ /**
78
+ * Fetch meetings via the SDK and format them as a human-readable summary
79
+ * including AI-generated summaries and action items.
80
+ */
81
+ async function executeMeetingsTool(client, input) {
82
+ const options = {
83
+ expand: ["summary", "short_summary", "action_items", "attendees"],
84
+ };
85
+ if (input.start_date) {
86
+ options.startDate = input.start_date;
87
+ }
88
+ if (input.end_date) {
89
+ options.endDate = input.end_date;
90
+ }
91
+ if (input.provider) {
92
+ options.provider = input.provider;
93
+ }
94
+ options.limit = Math.max(1, Math.min(input.limit ?? 10, 50));
95
+ const response = await client.meetings.list(options);
96
+ if (!response.data) {
97
+ // prettier-ignore
98
+ console.error("[AttroveMCP]", JSON.stringify({ level: "warn", msg: "Meetings API returned success but data was nullish", errorId: "MCP_MEETINGS_MALFORMED_RESPONSE" }));
99
+ return "The meetings API returned an unexpected response format. Please try again.";
100
+ }
101
+ if (response.data.length === 0) {
102
+ return "No meetings found for the specified date range.";
103
+ }
104
+ const meetings = response.data;
105
+ let result = `Found ${meetings.length} meeting(s):\n`;
106
+ for (const meeting of meetings) {
107
+ result += `\n### ${meeting.title}\n`;
108
+ result += `- **When:** ${formatMeetingTime(meeting)}\n`;
109
+ if (meeting.provider) {
110
+ const providerLabel = meeting.provider
111
+ .replace(/_/g, " ")
112
+ .replace(/\b\w/g, (c) => c.toUpperCase());
113
+ result += `- **Provider:** ${providerLabel}\n`;
114
+ }
115
+ if (meeting.attendees?.length) {
116
+ const attendeeList = meeting.attendees
117
+ .map((a) => {
118
+ const name = a.name || a.email || "Unknown";
119
+ const role = a.is_organizer ? " (organizer)" : "";
120
+ return `${name}${role}`;
121
+ })
122
+ .join(", ");
123
+ result += `- **Attendees:** ${attendeeList}\n`;
124
+ }
125
+ if (meeting.meeting_link) {
126
+ result += `- **Meeting link:** ${meeting.meeting_link}\n`;
127
+ }
128
+ if (meeting.summary) {
129
+ result += `\n**Summary:**\n${meeting.summary}\n`;
130
+ }
131
+ else if (meeting.short_summary) {
132
+ result += `\n**Summary:** ${meeting.short_summary}\n`;
133
+ }
134
+ if (meeting.action_items?.length) {
135
+ result += `\n**Action Items:**\n`;
136
+ for (const item of meeting.action_items) {
137
+ const assignee = item.assignee ? ` (${item.assignee})` : "";
138
+ const dueDate = item.due_date ? ` — due ${item.due_date}` : "";
139
+ const status = item.completed ? " [Done]" : "";
140
+ result += `- ${item.description}${assignee}${dueDate}${status}\n`;
141
+ }
142
+ }
143
+ }
144
+ if (response.pagination?.has_more) {
145
+ result += `\n_Showing ${meetings.length} of ${response.pagination.total_count ?? "more"} meetings. Adjust start_date, end_date, or limit to refine results._\n`;
146
+ }
147
+ return result;
148
+ }
149
+ exports.executeMeetingsTool = executeMeetingsTool;
@@ -11,15 +11,15 @@ exports.executeQueryTool = exports.queryToolDefinition = void 0;
11
11
  */
12
12
  exports.queryToolDefinition = {
13
13
  name: "attrove_query",
14
- description: `Ask a question about the user's communications and get an AI-generated answer.
14
+ description: `Ask a question and get an AI-generated answer from the user's own connected accounts.
15
15
 
16
- This tool searches across all connected integrations (Gmail, Slack, Google Meet, etc.) and returns a comprehensive answer based on the relevant context.
16
+ This read-only tool searches the authenticated user's connected services (e.g., Gmail, Slack, Google Calendar) and returns an answer based on their own data. Only data the user has explicitly connected and authorized is accessed.
17
17
 
18
18
  Use this tool when the user asks questions like:
19
19
  - "What did Sarah say about the Q4 budget?"
20
20
  - "Summarize my meeting with the engineering team"
21
21
  - "What are the action items from yesterday's standup?"
22
- - "When is my next meeting with John?"`,
22
+ - "What context do I need for my 3pm meeting?"`,
23
23
  inputSchema: {
24
24
  type: "object",
25
25
  properties: {
@@ -40,9 +40,16 @@ Use this tool when the user asks questions like:
40
40
  },
41
41
  required: ["query"],
42
42
  },
43
+ annotations: {
44
+ title: "Ask Attrove",
45
+ readOnlyHint: true,
46
+ destructiveHint: false,
47
+ idempotentHint: true,
48
+ openWorldHint: true,
49
+ },
43
50
  };
44
51
  /**
45
- * Execute the query tool.
52
+ * Run a RAG query via the SDK and format the answer with optional sources.
46
53
  */
47
54
  async function executeQueryTool(client, input) {
48
55
  const options = {};
@@ -61,7 +68,7 @@ async function executeQueryTool(client, input) {
61
68
  result += `\n- ${source.title}: "${source.snippet}"`;
62
69
  }
63
70
  }
64
- if (response.used_message_ids.length > 0) {
71
+ if (response.used_message_ids?.length) {
65
72
  result += `\n\n_Based on ${response.used_message_ids.length} messages._`;
66
73
  }
67
74
  return result;
@@ -12,10 +12,10 @@ const constants_js_1 = require("../constants.js");
12
12
  */
13
13
  exports.searchToolDefinition = {
14
14
  name: "attrove_search",
15
- description: `Search for specific messages or conversations in the user's communications.
15
+ description: `Search for messages or conversations in the user's own connected accounts.
16
16
 
17
- This tool performs semantic search across connected integrations and returns matching messages grouped by conversation. Use this when you need:
18
- - Raw message data without AI summarization
17
+ This read-only tool performs semantic search across the authenticated user's connected services and returns matching messages grouped by conversation. Only the user's own authorized data is searched. Use this when you need:
18
+ - Message data without AI summarization
19
19
  - To find specific conversations or threads
20
20
  - To explore what information is available about a topic
21
21
 
@@ -45,15 +45,23 @@ Use this tool when the user asks things like:
45
45
  },
46
46
  include_body_text: {
47
47
  type: "boolean",
48
- description: "Optional: Include full message body text",
48
+ // NOTE: The "200 characters" must match MAX_BODY_PREVIEW_LENGTH in constants.ts
49
+ description: "Optional: Include message body text preview (truncated to 200 characters)",
49
50
  default: true,
50
51
  },
51
52
  },
52
53
  required: ["query"],
53
54
  },
55
+ annotations: {
56
+ title: "Search Messages",
57
+ readOnlyHint: true,
58
+ destructiveHint: false,
59
+ idempotentHint: true,
60
+ openWorldHint: true,
61
+ },
54
62
  };
55
63
  /**
56
- * Execute the search tool.
64
+ * Search user messages via the SDK and format results grouped by conversation.
57
65
  */
58
66
  async function executeSearchTool(client, input) {
59
67
  const options = {
@@ -85,17 +93,21 @@ async function executeSearchTool(client, input) {
85
93
  let skippedThreads = 0;
86
94
  let skippedMessages = 0;
87
95
  for (const [convId, conv] of Object.entries(response.conversations)) {
88
- // Skip malformed conversation entries
96
+ // Skip malformed conversation entries - may occur with API version mismatches or partial responses
89
97
  if (!conv || !conv.threads) {
90
98
  skippedConversations++;
99
+ // prettier-ignore
100
+ console.error("[AttroveMCP]", JSON.stringify({ level: "warn", msg: "Search skipped malformed conversation", errorId: "MCP_SEARCH_MALFORMED_CONVERSATION", conversationId: convId, hasConv: !!conv, hasThreads: !!(conv?.threads) }));
91
101
  continue;
92
102
  }
93
103
  const convName = conv.conversation_name || `Conversation ${convId}`;
94
104
  result += `\n## ${convName}\n`;
95
105
  for (const [threadId, messages] of Object.entries(conv.threads)) {
96
- // Skip malformed thread entries
106
+ // Skip malformed thread entries - may occur with API version mismatches or partial responses
97
107
  if (!Array.isArray(messages)) {
98
108
  skippedThreads++;
109
+ // prettier-ignore
110
+ console.error("[AttroveMCP]", JSON.stringify({ level: "warn", msg: "Search skipped malformed thread", errorId: "MCP_SEARCH_MALFORMED_THREAD", conversationId: convId, threadId, messagesType: typeof messages }));
99
111
  continue;
100
112
  }
101
113
  if (messages.length > 1) {
@@ -104,6 +116,8 @@ async function executeSearchTool(client, input) {
104
116
  for (const msg of messages) {
105
117
  if (!msg) {
106
118
  skippedMessages++;
119
+ // prettier-ignore
120
+ console.error("[AttroveMCP]", JSON.stringify({ level: "warn", msg: "Search skipped null message", errorId: "MCP_SEARCH_NULL_MESSAGE", conversationId: convId, threadId }));
107
121
  continue;
108
122
  }
109
123
  // Defensive date formatting to handle invalid dates gracefully
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ /**
3
+ * HTTP Transport for Attrove MCP Server
4
+ *
5
+ * Provides HTTP-based transport for the MCP server, enabling AI assistants
6
+ * like ChatGPT to connect via HTTP endpoints instead of stdio.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.createHttpHandler = void 0;
10
+ const node_crypto_1 = require("node:crypto");
11
+ const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
12
+ const server_js_1 = require("../server.js");
13
+ /**
14
+ * Create an HTTP request handler for the MCP server.
15
+ *
16
+ * Each call to handleRequest creates new server and transport instances,
17
+ * providing complete isolation between requests. Callers should create
18
+ * a new handler when the config (API key/user ID) changes.
19
+ *
20
+ * @param config - MCP server configuration with API key and user ID
21
+ * @param options - Optional handler configuration
22
+ * @returns Object with handleRequest method for processing HTTP requests
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * // In a Fastify route handler
27
+ * const handler = createHttpHandler({
28
+ * apiKey: 'sk_...',
29
+ * userId: 'user-uuid',
30
+ * baseUrl: 'https://api.attrove.com', // optional, SDK has its own default
31
+ * });
32
+ *
33
+ * // Handle POST request
34
+ * const result = await handler.handleRequest(req.raw, reply.raw, req.body);
35
+ * if (!result.handled) {
36
+ * // No response sent - caller must send error response
37
+ * res.status(500).json({ error: result.error });
38
+ * }
39
+ * ```
40
+ */
41
+ /**
42
+ * Type guard for Node.js system errors with error codes.
43
+ */
44
+ function isNodeError(error) {
45
+ return error instanceof Error && "code" in error;
46
+ }
47
+ function createHttpHandler(config, options = {}) {
48
+ const { enableJsonResponse = true, timeoutMs = 30000 } = options;
49
+ // Validate timeoutMs to prevent unexpected behavior
50
+ if (timeoutMs <= 0) {
51
+ throw new Error("timeoutMs must be a positive number");
52
+ }
53
+ return {
54
+ /**
55
+ * Handle an incoming HTTP request.
56
+ *
57
+ * @param req - Node.js IncomingMessage (or Fastify raw request)
58
+ * @param res - Node.js ServerResponse (or Fastify raw reply)
59
+ * @param parsedBody - Pre-parsed request body (optional, Fastify provides this)
60
+ * @returns Promise resolving to handler result indicating if request was processed
61
+ */
62
+ handleRequest: async (req, res, parsedBody) => {
63
+ let server;
64
+ let timeoutId;
65
+ let result;
66
+ let cleanupFailed = false;
67
+ let timeoutOccurred = false;
68
+ // Correlation ID links timeout errors with subsequent suppressed errors for debugging
69
+ const correlationId = (0, node_crypto_1.randomUUID)().slice(0, 8);
70
+ try {
71
+ server = (0, server_js_1.createServer)(config);
72
+ const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
73
+ sessionIdGenerator: undefined, // Stateless mode - no session tracking needed
74
+ enableJsonResponse,
75
+ });
76
+ await server.connect(transport);
77
+ const timeoutPromise = new Promise((_, reject) => {
78
+ timeoutId = setTimeout(() => {
79
+ timeoutOccurred = true;
80
+ reject(new Error(`MCP request timed out after ${timeoutMs}ms`));
81
+ }, timeoutMs);
82
+ });
83
+ // Store reference to transport promise so we can attach a catch handler.
84
+ // This prevents unhandled rejection if timeout wins the race and server.close()
85
+ // later causes the transport to reject.
86
+ const transportPromise = transport.handleRequest(req, res, parsedBody);
87
+ // When timeout occurs, Promise.race exits with the timeout error (caught below),
88
+ // but transportPromise may reject later when server.close() interrupts it.
89
+ // Only log here if a timeout actually occurred - otherwise Promise.race will
90
+ // propagate the rejection to the main catch block and logging here would be duplicate.
91
+ transportPromise.catch((suppressedError) => {
92
+ if (!timeoutOccurred) {
93
+ // No timeout - Promise.race will handle this rejection via the main catch block
94
+ return;
95
+ }
96
+ const errorMsg = suppressedError instanceof Error
97
+ ? suppressedError.message
98
+ : String(suppressedError);
99
+ // Critical errors that indicate systemic issues (not just slow requests)
100
+ const isCritical = /SSL|certificate|ENOTFOUND|ECONNREFUSED|auth/i.test(errorMsg);
101
+ const logData = {
102
+ level: isCritical ? "error" : "warn",
103
+ msg: "MCP transport rejected after timeout - suppressed to prevent unhandled rejection",
104
+ errorId: isCritical
105
+ ? "MCP_HTTP_SUPPRESSED_CRITICAL_ERROR"
106
+ : "MCP_HTTP_SUPPRESSED_POST_TIMEOUT",
107
+ correlationId,
108
+ error: errorMsg,
109
+ userId: config.userId,
110
+ };
111
+ // prettier-ignore
112
+ console.error("[AttroveMCP]", JSON.stringify(logData));
113
+ });
114
+ await Promise.race([transportPromise, timeoutPromise]);
115
+ result = { handled: true };
116
+ }
117
+ catch (error) {
118
+ // Preserve context for non-Error values (e.g., throw "string", throw { code: ... })
119
+ const message = error instanceof Error
120
+ ? error.message
121
+ : typeof error === "object" && error !== null
122
+ ? `Unknown error: ${JSON.stringify(error)}`
123
+ : `Unknown error: ${String(error)}`;
124
+ const stack = error instanceof Error ? error.stack : undefined;
125
+ const isTimeout = error instanceof Error && error.message.includes("timed out");
126
+ // Classify error type for appropriate logging level
127
+ // Use error.code for socket errors (more precise than string matching)
128
+ const isSocketError = isNodeError(error) &&
129
+ (error.code === "ECONNRESET" ||
130
+ error.code === "EPIPE" ||
131
+ error.code === "ECONNABORTED");
132
+ const isExpectedError = isTimeout || isSocketError;
133
+ // Log with structured JSON for observability (callers should also log via their infrastructure)
134
+ const errorId = isTimeout
135
+ ? "MCP_HTTP_TIMEOUT"
136
+ : isSocketError
137
+ ? "MCP_HTTP_SOCKET_ERROR"
138
+ : "MCP_HTTP_UNEXPECTED_ERROR";
139
+ const logData = {
140
+ level: isExpectedError ? "warn" : "error",
141
+ msg: isExpectedError
142
+ ? "MCP HTTP handler operational failure"
143
+ : "MCP HTTP handler unexpected failure",
144
+ errorId,
145
+ correlationId,
146
+ error: message,
147
+ isTimeout,
148
+ userId: config.userId,
149
+ ...(stack && !isExpectedError && { stack }),
150
+ ...(!isExpectedError && { errorType: error?.constructor?.name }),
151
+ };
152
+ // prettier-ignore
153
+ console.error("[AttroveMCP]", JSON.stringify(logData));
154
+ result = { handled: false, error: message, stack, isTimeout };
155
+ }
156
+ finally {
157
+ // Clear timeout to prevent timer accumulation under load
158
+ if (timeoutId !== undefined) {
159
+ clearTimeout(timeoutId);
160
+ }
161
+ if (server) {
162
+ try {
163
+ await server.close();
164
+ }
165
+ catch (cleanupError) {
166
+ cleanupFailed = true;
167
+ // Cleanup failures could indicate resource leaks - always log for monitoring
168
+ const cleanupLogData = {
169
+ level: "error",
170
+ msg: "MCP server cleanup failed - potential resource leak",
171
+ errorId: "MCP_CLEANUP_FAILURE",
172
+ correlationId,
173
+ error: cleanupError instanceof Error
174
+ ? cleanupError.message
175
+ : String(cleanupError),
176
+ stack: cleanupError instanceof Error ? cleanupError.stack : undefined,
177
+ userId: config.userId,
178
+ };
179
+ // prettier-ignore
180
+ console.error("[AttroveMCP]", JSON.stringify(cleanupLogData));
181
+ }
182
+ }
183
+ }
184
+ // Include cleanup failure warning in success result for monitoring
185
+ if (result.handled && cleanupFailed) {
186
+ return { handled: true, cleanupFailed: true };
187
+ }
188
+ return result;
189
+ },
190
+ };
191
+ }
192
+ exports.createHttpHandler = createHttpHandler;
package/esm/index.d.ts CHANGED
@@ -28,6 +28,8 @@
28
28
  */
29
29
  export { createServer, startServer, getConfigFromEnv } from "./server.js";
30
30
  export type { McpServerConfig } from "./server.js";
31
- export { allToolDefinitions, queryToolDefinition, searchToolDefinition, integrationsToolDefinition, } from "./tools/index.js";
31
+ export { allToolDefinitions, queryToolDefinition, searchToolDefinition, integrationsToolDefinition, eventsToolDefinition, meetingsToolDefinition, } from "./tools/index.js";
32
32
  export { getVersion } from "./version.js";
33
+ export { createHttpHandler } from "./transport/http.js";
34
+ export type { McpHttpHandler, McpHttpHandlerResult, McpHttpHandlerFailure, CreateHttpHandlerOptions, } from "./transport/http.js";
33
35
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../packages/mcp/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1E,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../packages/mcp/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1E,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC"}
package/esm/index.js CHANGED
@@ -27,6 +27,8 @@
27
27
  * @packageDocumentation
28
28
  */
29
29
  export { createServer, startServer, getConfigFromEnv } from "./server.js";
30
- export { allToolDefinitions, queryToolDefinition, searchToolDefinition, integrationsToolDefinition, } from "./tools/index.js";
30
+ export { allToolDefinitions, queryToolDefinition, searchToolDefinition, integrationsToolDefinition, eventsToolDefinition, meetingsToolDefinition, } from "./tools/index.js";
31
31
  export { getVersion } from "./version.js";
32
+ // HTTP transport for hosted MCP endpoints
33
+ export { createHttpHandler } from "./transport/http.js";
32
34
  //# sourceMappingURL=index.js.map
package/esm/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/mcp/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG1E,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/mcp/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG1E,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,0CAA0C;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
package/esm/server.d.ts CHANGED
@@ -5,35 +5,37 @@
5
5
  * to access user context through the Attrove API.
6
6
  */
7
7
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
8
+ import { ApiKeyFormat } from "@attrove/sdk";
8
9
  /**
9
10
  * Configuration for the MCP server.
10
11
  */
11
12
  export interface McpServerConfig {
12
13
  /**
13
14
  * Attrove API key (sk_ prefixed).
15
+ * Must be a valid ApiKeyFormat string starting with "sk_".
14
16
  */
15
- apiKey: string;
17
+ apiKey: ApiKeyFormat;
16
18
  /**
17
19
  * User ID (UUID) to scope API calls.
18
20
  */
19
21
  userId: string;
20
22
  /**
21
- * Optional API base URL.
23
+ * Optional API base URL. If not specified, the SDK's default is used.
22
24
  */
23
25
  baseUrl?: string;
24
26
  }
25
27
  /**
26
- * Create and configure the Attrove MCP server.
28
+ * Wire up tool definitions and dispatch logic for the Attrove MCP server.
27
29
  */
28
30
  export declare function createServer(config: McpServerConfig): Server;
29
31
  /**
30
- * Start the MCP server with stdio transport.
32
+ * Connect the MCP server to stdin/stdout and begin serving requests.
31
33
  */
32
34
  export declare function startServer(config: McpServerConfig): Promise<void>;
33
35
  /**
34
36
  * Get configuration from environment variables.
35
37
  *
36
- * @throws {Error} If required environment variables are missing
38
+ * @throws {Error} If required environment variables are missing or invalid
37
39
  */
38
40
  export declare function getConfigFromEnv(): McpServerConfig;
39
41
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../packages/mcp/src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAgEnE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAiID;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAgH5D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,eAAe,CAwBlD"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../packages/mcp/src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAMnE,OAAO,EAKL,YAAY,EAEb,MAAM,cAAc,CAAC;AAuDtB;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,MAAM,EAAE,YAAY,CAAC;IAErB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAgQD;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAgG5D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,eAAe,CA8BlD"}