@apteva/integrations 0.1.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 (42) hide show
  1. package/dist/apps/index.d.ts +25 -0
  2. package/dist/apps/index.d.ts.map +1 -0
  3. package/dist/apps/index.js +51 -0
  4. package/dist/apps/index.js.map +1 -0
  5. package/dist/http-executor.d.ts +21 -0
  6. package/dist/http-executor.d.ts.map +1 -0
  7. package/dist/http-executor.js +191 -0
  8. package/dist/http-executor.js.map +1 -0
  9. package/dist/index.d.ts +12 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +13 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/mcp-generator.d.ts +8 -0
  14. package/dist/mcp-generator.d.ts.map +1 -0
  15. package/dist/mcp-generator.js +108 -0
  16. package/dist/mcp-generator.js.map +1 -0
  17. package/dist/oauth.d.ts +49 -0
  18. package/dist/oauth.d.ts.map +1 -0
  19. package/dist/oauth.js +119 -0
  20. package/dist/oauth.js.map +1 -0
  21. package/dist/providers/local.d.ts +55 -0
  22. package/dist/providers/local.d.ts.map +1 -0
  23. package/dist/providers/local.js +209 -0
  24. package/dist/providers/local.js.map +1 -0
  25. package/dist/triggers/local.d.ts +55 -0
  26. package/dist/triggers/local.d.ts.map +1 -0
  27. package/dist/triggers/local.js +103 -0
  28. package/dist/triggers/local.js.map +1 -0
  29. package/dist/types.d.ts +96 -0
  30. package/dist/types.d.ts.map +1 -0
  31. package/dist/types.js +3 -0
  32. package/dist/types.js.map +1 -0
  33. package/package.json +42 -0
  34. package/src/apps/github.json +96 -0
  35. package/src/apps/gmail.json +62 -0
  36. package/src/apps/google-calendar.json +68 -0
  37. package/src/apps/linear.json +85 -0
  38. package/src/apps/notion.json +102 -0
  39. package/src/apps/pushover.json +56 -0
  40. package/src/apps/sendgrid.json +63 -0
  41. package/src/apps/slack.json +74 -0
  42. package/src/apps/stripe.json +85 -0
@@ -0,0 +1,25 @@
1
+ import type { AppTemplate } from "../types.js";
2
+ /**
3
+ * Load all app templates from the JSON files in this directory.
4
+ * Results are cached after first load.
5
+ */
6
+ export declare function loadAppTemplates(): Map<string, AppTemplate>;
7
+ /**
8
+ * Get a single app template by slug.
9
+ */
10
+ export declare function getAppTemplate(slug: string): AppTemplate | undefined;
11
+ /**
12
+ * List all available app slugs.
13
+ */
14
+ export declare function listAppSlugs(): string[];
15
+ /**
16
+ * List all app templates with basic info (no full tool schemas).
17
+ */
18
+ export declare function listApps(): Array<{
19
+ slug: string;
20
+ name: string;
21
+ description: string;
22
+ categories: string[];
23
+ toolCount: number;
24
+ }>;
25
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/apps/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAiB3D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEpE;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAEvC;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,KAAK,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC,CAQD"}
@@ -0,0 +1,51 @@
1
+ import { readFileSync, readdirSync } from "fs";
2
+ import { join, dirname } from "path";
3
+ import { fileURLToPath } from "url";
4
+ const __dirname = dirname(fileURLToPath(import.meta.url));
5
+ let cachedApps = null;
6
+ /**
7
+ * Load all app templates from the JSON files in this directory.
8
+ * Results are cached after first load.
9
+ */
10
+ export function loadAppTemplates() {
11
+ if (cachedApps)
12
+ return cachedApps;
13
+ cachedApps = new Map();
14
+ const files = readdirSync(__dirname).filter((f) => f.endsWith(".json"));
15
+ for (const file of files) {
16
+ try {
17
+ const raw = readFileSync(join(__dirname, file), "utf-8");
18
+ const app = JSON.parse(raw);
19
+ cachedApps.set(app.slug, app);
20
+ }
21
+ catch (e) {
22
+ console.warn(`[integrations] Failed to load app template ${file}:`, e);
23
+ }
24
+ }
25
+ return cachedApps;
26
+ }
27
+ /**
28
+ * Get a single app template by slug.
29
+ */
30
+ export function getAppTemplate(slug) {
31
+ return loadAppTemplates().get(slug);
32
+ }
33
+ /**
34
+ * List all available app slugs.
35
+ */
36
+ export function listAppSlugs() {
37
+ return Array.from(loadAppTemplates().keys());
38
+ }
39
+ /**
40
+ * List all app templates with basic info (no full tool schemas).
41
+ */
42
+ export function listApps() {
43
+ return Array.from(loadAppTemplates().values()).map((app) => ({
44
+ slug: app.slug,
45
+ name: app.name,
46
+ description: app.description,
47
+ categories: app.categories,
48
+ toolCount: app.tools.length,
49
+ }));
50
+ }
51
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/apps/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAGpC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,IAAI,UAAU,GAAoC,IAAI,CAAC;AAEvD;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAElC,UAAU,GAAG,IAAI,GAAG,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAExE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;YACzD,MAAM,GAAG,GAAgB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,8CAA8C,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,gBAAgB,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ;IAOtB,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC3D,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM;KAC5B,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { AppTemplate, AppToolTemplate, ConnectionCredentials } from "./types.js";
2
+ export interface ExecuteToolOptions {
3
+ app: AppTemplate;
4
+ tool: AppToolTemplate;
5
+ credentials: ConnectionCredentials;
6
+ input: Record<string, unknown>;
7
+ timeout?: number;
8
+ }
9
+ export interface ExecuteToolResult {
10
+ success: boolean;
11
+ status: number;
12
+ data: unknown;
13
+ headers: Record<string, string>;
14
+ }
15
+ /**
16
+ * Execute an HTTP-based tool call against a real API.
17
+ * Takes an app template, tool definition, connection credentials, and input params,
18
+ * then makes the actual HTTP request and returns the result.
19
+ */
20
+ export declare function executeTool(opts: ExecuteToolOptions): Promise<ExecuteToolResult>;
21
+ //# sourceMappingURL=http-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-executor.d.ts","sourceRoot":"","sources":["../src/http-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EAEf,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,WAAW,CAAC;IACjB,IAAI,EAAE,eAAe,CAAC;IACtB,WAAW,EAAE,qBAAqB,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,iBAAiB,CAAC,CA+F5B"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Execute an HTTP-based tool call against a real API.
3
+ * Takes an app template, tool definition, connection credentials, and input params,
4
+ * then makes the actual HTTP request and returns the result.
5
+ */
6
+ export async function executeTool(opts) {
7
+ const { app, tool, credentials, input, timeout = 30000 } = opts;
8
+ // 1. Build the URL with path parameter interpolation
9
+ const url = buildUrl(app.base_url, tool.path, input);
10
+ // 2. Build headers from app auth config + credentials
11
+ const headers = buildHeaders(app, credentials);
12
+ // 3. Build request options
13
+ const fetchOpts = {
14
+ method: tool.method,
15
+ headers,
16
+ signal: AbortSignal.timeout(timeout),
17
+ };
18
+ // 4. Build auth query params (e.g. Pushover's ?token=xxx)
19
+ const authQueryParams = buildAuthQueryParams(app, credentials);
20
+ // 5. For GET/DELETE, remaining params go to query string.
21
+ // For POST/PUT/PATCH, remaining params go to body.
22
+ const pathParams = extractPathParams(tool.path);
23
+ const remainingParams = Object.fromEntries(Object.entries(input).filter(([k]) => !pathParams.includes(k)));
24
+ let finalUrl = url;
25
+ const allQueryParams = { ...authQueryParams };
26
+ if (tool.method === "GET" || tool.method === "DELETE") {
27
+ Object.assign(allQueryParams, remainingParams);
28
+ }
29
+ else {
30
+ // For POST with query_params auth (like Pushover), merge auth + input into body
31
+ if (Object.keys(authQueryParams).length > 0) {
32
+ // API-key APIs like Pushover expect token in the POST body too
33
+ const bodyParams = { ...authQueryParams, ...remainingParams };
34
+ const contentType = headers["Content-Type"] || headers["content-type"] || "";
35
+ if (contentType.includes("x-www-form-urlencoded")) {
36
+ fetchOpts.body = buildQueryString(bodyParams);
37
+ }
38
+ else {
39
+ fetchOpts.body = JSON.stringify(bodyParams);
40
+ }
41
+ }
42
+ else {
43
+ const contentType = headers["Content-Type"] || headers["content-type"] || "";
44
+ if (contentType.includes("x-www-form-urlencoded")) {
45
+ fetchOpts.body = buildQueryString(remainingParams);
46
+ }
47
+ else {
48
+ fetchOpts.body = JSON.stringify(remainingParams);
49
+ }
50
+ }
51
+ }
52
+ // Append query params to URL for GET/DELETE (or auth params for any method)
53
+ if (tool.method === "GET" || tool.method === "DELETE") {
54
+ const qs = buildQueryString(allQueryParams);
55
+ if (qs)
56
+ finalUrl += `?${qs}`;
57
+ }
58
+ // 5. Execute the request
59
+ try {
60
+ const response = await fetch(finalUrl, fetchOpts);
61
+ const responseHeaders = {};
62
+ response.headers.forEach((v, k) => {
63
+ responseHeaders[k] = v;
64
+ });
65
+ let data;
66
+ const ct = response.headers.get("content-type") || "";
67
+ if (ct.includes("application/json")) {
68
+ data = await response.json();
69
+ }
70
+ else {
71
+ data = await response.text();
72
+ }
73
+ // Apply response_path extraction if defined
74
+ if (tool.response_path && data && typeof data === "object") {
75
+ data = extractPath(data, tool.response_path);
76
+ }
77
+ return {
78
+ success: response.ok,
79
+ status: response.status,
80
+ data,
81
+ headers: responseHeaders,
82
+ };
83
+ }
84
+ catch (error) {
85
+ const message = error instanceof Error ? error.message : "Unknown error";
86
+ return {
87
+ success: false,
88
+ status: 0,
89
+ data: { error: message },
90
+ headers: {},
91
+ };
92
+ }
93
+ }
94
+ // ─── Helpers ───
95
+ function buildUrl(baseUrl, path, input) {
96
+ // Replace {param} placeholders with actual values
97
+ let resolved = path;
98
+ const paramRegex = /\{(\w+)\}/g;
99
+ let match;
100
+ while ((match = paramRegex.exec(path)) !== null) {
101
+ const key = match[1];
102
+ const value = input[key];
103
+ if (value !== undefined) {
104
+ resolved = resolved.replace(`{${key}}`, encodeURIComponent(String(value)));
105
+ }
106
+ }
107
+ return `${baseUrl.replace(/\/$/, "")}${resolved}`;
108
+ }
109
+ function extractPathParams(path) {
110
+ const params = [];
111
+ const regex = /\{(\w+)\}/g;
112
+ let match;
113
+ while ((match = regex.exec(path)) !== null) {
114
+ params.push(match[1]);
115
+ }
116
+ return params;
117
+ }
118
+ function buildAuthQueryParams(app, credentials) {
119
+ const params = {};
120
+ if (app.auth.query_params) {
121
+ for (const [key, template] of Object.entries(app.auth.query_params)) {
122
+ params[key] = resolveTemplate(template, credentials);
123
+ }
124
+ }
125
+ return params;
126
+ }
127
+ function buildHeaders(app, credentials) {
128
+ const headers = {};
129
+ if (app.auth.headers) {
130
+ for (const [key, template] of Object.entries(app.auth.headers)) {
131
+ headers[key] = resolveTemplate(template, credentials);
132
+ }
133
+ }
134
+ return headers;
135
+ }
136
+ function resolveTemplate(template, credentials) {
137
+ return template.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
138
+ // Map common template vars to credential fields
139
+ switch (key) {
140
+ case "token":
141
+ return (credentials.access_token ||
142
+ credentials.bearer_token ||
143
+ credentials.api_key ||
144
+ "");
145
+ case "api_key":
146
+ return credentials.api_key || "";
147
+ case "username":
148
+ return credentials.username || "";
149
+ case "password":
150
+ return credentials.password || "";
151
+ default:
152
+ return credentials.fields?.[key] || "";
153
+ }
154
+ });
155
+ }
156
+ function buildQueryString(params) {
157
+ const parts = [];
158
+ for (const [key, value] of Object.entries(params)) {
159
+ if (value === undefined || value === null)
160
+ continue;
161
+ if (Array.isArray(value)) {
162
+ for (const item of value) {
163
+ parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(item))}`);
164
+ }
165
+ }
166
+ else if (typeof value === "object") {
167
+ parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(value))}`);
168
+ }
169
+ else {
170
+ parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
171
+ }
172
+ }
173
+ return parts.join("&");
174
+ }
175
+ function extractPath(data, jsonPath) {
176
+ // Simple dot-notation path extraction: "data.items"
177
+ const parts = jsonPath.split(".");
178
+ let current = data;
179
+ for (const part of parts) {
180
+ if (current === null || current === undefined)
181
+ return current;
182
+ if (typeof current === "object") {
183
+ current = current[part];
184
+ }
185
+ else {
186
+ return undefined;
187
+ }
188
+ }
189
+ return current;
190
+ }
191
+ //# sourceMappingURL=http-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-executor.js","sourceRoot":"","sources":["../src/http-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export type { AppTemplate, AppAuthConfig, AuthType, OAuthConfig, AppToolTemplate, Connection, ConnectionCredentials, LocalTriggerConfig, GeneratedMcpServer, GeneratedMcpTool, IntegrationsStorage, } from "./types.js";
2
+ export { loadAppTemplates, getAppTemplate, listAppSlugs, listApps, } from "./apps/index.js";
3
+ export { executeTool } from "./http-executor.js";
4
+ export type { ExecuteToolOptions, ExecuteToolResult } from "./http-executor.js";
5
+ export { getAuthorizationUrl, exchangeCode, refreshAccessToken, tokensToCredentials, isTokenExpired, } from "./oauth.js";
6
+ export type { OAuthStartOptions, OAuthCallbackOptions, OAuthRefreshOptions, OAuthTokenResult, } from "./oauth.js";
7
+ export { generateMcpServer } from "./mcp-generator.js";
8
+ export { LocalIntegrationProvider } from "./providers/local.js";
9
+ export type { LocalProviderConfig } from "./providers/local.js";
10
+ export { LocalTriggerProvider } from "./triggers/local.js";
11
+ export type { TriggerStorage, WebhookPayload, TriggerResult } from "./triggers/local.js";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,WAAW,EACX,aAAa,EACb,QAAQ,EACR,WAAW,EACX,eAAe,EACf,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGhF,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAGhE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ // ─── App Templates ───
2
+ export { loadAppTemplates, getAppTemplate, listAppSlugs, listApps, } from "./apps/index.js";
3
+ // ─── HTTP Tool Executor ───
4
+ export { executeTool } from "./http-executor.js";
5
+ // ─── OAuth Engine ───
6
+ export { getAuthorizationUrl, exchangeCode, refreshAccessToken, tokensToCredentials, isTokenExpired, } from "./oauth.js";
7
+ // ─── MCP Server Generator ───
8
+ export { generateMcpServer } from "./mcp-generator.js";
9
+ // ─── Local Integration Provider ───
10
+ export { LocalIntegrationProvider } from "./providers/local.js";
11
+ // ─── Local Trigger Provider ───
12
+ export { LocalTriggerProvider } from "./triggers/local.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,wBAAwB;AACxB,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,6BAA6B;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,uBAAuB;AACvB,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,GACf,MAAM,YAAY,CAAC;AAQpB,+BAA+B;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,qCAAqC;AACrC,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAGhE,iCAAiC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { AppTemplate, Connection, GeneratedMcpServer } from "./types.js";
2
+ /**
3
+ * Generate an MCP server definition from a connection + its app template.
4
+ * The generated server contains tools that map to HTTP API calls,
5
+ * with credentials baked into the headers.
6
+ */
7
+ export declare function generateMcpServer(connection: Connection, app: AppTemplate): GeneratedMcpServer;
8
+ //# sourceMappingURL=mcp-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-generator.d.ts","sourceRoot":"","sources":["../src/mcp-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,UAAU,EACV,kBAAkB,EAEnB,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,WAAW,GACf,kBAAkB,CAWpB"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Generate an MCP server definition from a connection + its app template.
3
+ * The generated server contains tools that map to HTTP API calls,
4
+ * with credentials baked into the headers.
5
+ */
6
+ export function generateMcpServer(connection, app) {
7
+ const tools = app.tools.map((tool) => generateMcpTool(app, tool, connection));
8
+ return {
9
+ name: `${app.slug}-${connection.id}`,
10
+ type: "local",
11
+ source: "local-integration",
12
+ tools,
13
+ };
14
+ }
15
+ /**
16
+ * Generate a single MCP tool from an app tool template + connection.
17
+ */
18
+ function generateMcpTool(app, tool, connection) {
19
+ // Build resolved headers with actual credentials
20
+ const headers = {};
21
+ if (app.auth.headers) {
22
+ for (const [key, template] of Object.entries(app.auth.headers)) {
23
+ headers[key] = resolveCredentialTemplate(template, connection.credentials);
24
+ }
25
+ }
26
+ // Build auth query params (e.g. Pushover's ?token=xxx) and bake into URL
27
+ let authQuery = "";
28
+ if (app.auth.query_params) {
29
+ const parts = [];
30
+ for (const [key, template] of Object.entries(app.auth.query_params)) {
31
+ const value = resolveCredentialTemplate(template, connection.credentials);
32
+ parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
33
+ }
34
+ if (parts.length > 0)
35
+ authQuery = `?${parts.join("&")}`;
36
+ }
37
+ // Build the full URL template (path params remain as {param} for runtime resolution)
38
+ const url = `${app.base_url.replace(/\/$/, "")}${tool.path}${authQuery}`;
39
+ // For POST/PUT/PATCH, generate a body template
40
+ let bodyTemplate;
41
+ if (tool.method !== "GET" && tool.method !== "DELETE") {
42
+ // The body template uses the tool's input_schema properties as a hint.
43
+ // At runtime, the MCP handler will JSON.stringify the input minus path params.
44
+ bodyTemplate = "{{json_body}}";
45
+ }
46
+ // Build clean input schema without path params (those get resolved in URL)
47
+ const pathParams = extractPathParams(tool.path);
48
+ const cleanSchema = removePathParamsFromSchema(tool.input_schema, pathParams);
49
+ return {
50
+ name: `${app.slug}_${tool.name}`,
51
+ description: `[${app.name}] ${tool.description}`,
52
+ input_schema: cleanSchema,
53
+ handler_type: "http",
54
+ http_config: {
55
+ method: tool.method,
56
+ url,
57
+ headers,
58
+ body_template: bodyTemplate,
59
+ },
60
+ };
61
+ }
62
+ // ─── Helpers ───
63
+ function resolveCredentialTemplate(template, credentials) {
64
+ return template.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
65
+ switch (key) {
66
+ case "token":
67
+ return (credentials.access_token ||
68
+ credentials.bearer_token ||
69
+ credentials.api_key ||
70
+ "");
71
+ case "api_key":
72
+ return credentials.api_key || "";
73
+ case "username":
74
+ return credentials.username || "";
75
+ case "password":
76
+ return credentials.password || "";
77
+ default:
78
+ return credentials.fields?.[key] || "";
79
+ }
80
+ });
81
+ }
82
+ function extractPathParams(path) {
83
+ const params = [];
84
+ const regex = /\{(\w+)\}/g;
85
+ let match;
86
+ while ((match = regex.exec(path)) !== null) {
87
+ params.push(match[1]);
88
+ }
89
+ return params;
90
+ }
91
+ function removePathParamsFromSchema(schema, pathParams) {
92
+ if (pathParams.length === 0)
93
+ return schema;
94
+ const clone = JSON.parse(JSON.stringify(schema));
95
+ if (clone.properties) {
96
+ for (const param of pathParams) {
97
+ delete clone.properties[param];
98
+ }
99
+ // Also remove from required array
100
+ if (Array.isArray(clone.required)) {
101
+ clone.required = clone.required.filter((r) => !pathParams.includes(r));
102
+ if (clone.required.length === 0)
103
+ delete clone.required;
104
+ }
105
+ }
106
+ return clone;
107
+ }
108
+ //# sourceMappingURL=mcp-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-generator.js","sourceRoot":"","sources":["../src/mcp-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import type { AppTemplate, ConnectionCredentials } from "./types.js";
2
+ export interface OAuthStartOptions {
3
+ app: AppTemplate;
4
+ clientId: string;
5
+ redirectUri: string;
6
+ state?: string;
7
+ scopes?: string[];
8
+ }
9
+ export interface OAuthCallbackOptions {
10
+ app: AppTemplate;
11
+ clientId: string;
12
+ clientSecret: string;
13
+ redirectUri: string;
14
+ code: string;
15
+ }
16
+ export interface OAuthRefreshOptions {
17
+ app: AppTemplate;
18
+ clientId: string;
19
+ clientSecret: string;
20
+ refreshToken: string;
21
+ }
22
+ export interface OAuthTokenResult {
23
+ access_token: string;
24
+ refresh_token?: string;
25
+ expires_in?: number;
26
+ token_type?: string;
27
+ scope?: string;
28
+ }
29
+ /**
30
+ * Generate the OAuth2 authorization URL for a given app.
31
+ */
32
+ export declare function getAuthorizationUrl(opts: OAuthStartOptions): string;
33
+ /**
34
+ * Exchange an authorization code for access/refresh tokens.
35
+ */
36
+ export declare function exchangeCode(opts: OAuthCallbackOptions): Promise<OAuthTokenResult>;
37
+ /**
38
+ * Refresh an expired access token using a refresh token.
39
+ */
40
+ export declare function refreshAccessToken(opts: OAuthRefreshOptions): Promise<OAuthTokenResult>;
41
+ /**
42
+ * Convert OAuth tokens into ConnectionCredentials format.
43
+ */
44
+ export declare function tokensToCredentials(tokens: OAuthTokenResult, clientId?: string, clientSecret?: string): Partial<ConnectionCredentials>;
45
+ /**
46
+ * Check if a connection's token is expired or about to expire (within 5 min).
47
+ */
48
+ export declare function isTokenExpired(credentials: ConnectionCredentials): boolean;
49
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,WAAW,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,WAAW,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,WAAW,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAkBnE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CA4C3B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,gBAAgB,CAAC,CA8B3B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,gBAAgB,EACxB,QAAQ,CAAC,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,qBAAqB,CAAC,CAchC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAK1E"}
package/dist/oauth.js ADDED
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Generate the OAuth2 authorization URL for a given app.
3
+ */
4
+ export function getAuthorizationUrl(opts) {
5
+ const oauth = opts.app.auth.oauth2;
6
+ if (!oauth) {
7
+ throw new Error(`App "${opts.app.slug}" does not support OAuth2`);
8
+ }
9
+ const params = new URLSearchParams({
10
+ client_id: opts.clientId,
11
+ redirect_uri: opts.redirectUri,
12
+ response_type: "code",
13
+ scope: (opts.scopes || oauth.scopes).join(" "),
14
+ });
15
+ if (opts.state) {
16
+ params.set("state", opts.state);
17
+ }
18
+ return `${oauth.authorize_url}?${params.toString()}`;
19
+ }
20
+ /**
21
+ * Exchange an authorization code for access/refresh tokens.
22
+ */
23
+ export async function exchangeCode(opts) {
24
+ const oauth = opts.app.auth.oauth2;
25
+ if (!oauth) {
26
+ throw new Error(`App "${opts.app.slug}" does not support OAuth2`);
27
+ }
28
+ const body = new URLSearchParams({
29
+ grant_type: "authorization_code",
30
+ code: opts.code,
31
+ redirect_uri: opts.redirectUri,
32
+ client_id: opts.clientId,
33
+ client_secret: opts.clientSecret,
34
+ });
35
+ const response = await fetch(oauth.token_url, {
36
+ method: "POST",
37
+ headers: {
38
+ "Content-Type": "application/x-www-form-urlencoded",
39
+ Accept: "application/json",
40
+ },
41
+ body: body.toString(),
42
+ });
43
+ if (!response.ok) {
44
+ const text = await response.text();
45
+ throw new Error(`OAuth token exchange failed (${response.status}): ${text}`);
46
+ }
47
+ const contentType = response.headers.get("content-type") || "";
48
+ if (contentType.includes("application/json")) {
49
+ return (await response.json());
50
+ }
51
+ // Some providers (e.g. GitHub) return form-encoded
52
+ const text = await response.text();
53
+ const params = new URLSearchParams(text);
54
+ return {
55
+ access_token: params.get("access_token") || "",
56
+ refresh_token: params.get("refresh_token") || undefined,
57
+ token_type: params.get("token_type") || undefined,
58
+ scope: params.get("scope") || undefined,
59
+ };
60
+ }
61
+ /**
62
+ * Refresh an expired access token using a refresh token.
63
+ */
64
+ export async function refreshAccessToken(opts) {
65
+ const oauth = opts.app.auth.oauth2;
66
+ if (!oauth) {
67
+ throw new Error(`App "${opts.app.slug}" does not support OAuth2`);
68
+ }
69
+ const body = new URLSearchParams({
70
+ grant_type: "refresh_token",
71
+ refresh_token: opts.refreshToken,
72
+ client_id: opts.clientId,
73
+ client_secret: opts.clientSecret,
74
+ });
75
+ const response = await fetch(oauth.token_url, {
76
+ method: "POST",
77
+ headers: {
78
+ "Content-Type": "application/x-www-form-urlencoded",
79
+ Accept: "application/json",
80
+ },
81
+ body: body.toString(),
82
+ });
83
+ if (!response.ok) {
84
+ const text = await response.text();
85
+ throw new Error(`OAuth token refresh failed (${response.status}): ${text}`);
86
+ }
87
+ return (await response.json());
88
+ }
89
+ /**
90
+ * Convert OAuth tokens into ConnectionCredentials format.
91
+ */
92
+ export function tokensToCredentials(tokens, clientId, clientSecret) {
93
+ const creds = {
94
+ access_token: tokens.access_token,
95
+ };
96
+ if (tokens.refresh_token) {
97
+ creds.refresh_token = tokens.refresh_token;
98
+ }
99
+ if (tokens.expires_in) {
100
+ const expiresAt = new Date(Date.now() + tokens.expires_in * 1000);
101
+ creds.token_expires_at = expiresAt.toISOString();
102
+ }
103
+ if (clientId)
104
+ creds.client_id = clientId;
105
+ if (clientSecret)
106
+ creds.client_secret = clientSecret;
107
+ return creds;
108
+ }
109
+ /**
110
+ * Check if a connection's token is expired or about to expire (within 5 min).
111
+ */
112
+ export function isTokenExpired(credentials) {
113
+ if (!credentials.token_expires_at)
114
+ return false;
115
+ const expiresAt = new Date(credentials.token_expires_at).getTime();
116
+ const buffer = 5 * 60 * 1000; // 5 minutes
117
+ return Date.now() >= expiresAt - buffer;
118
+ }
119
+ //# sourceMappingURL=oauth.js.map