postgresai 0.11.0-alpha.12 → 0.11.0-alpha.13

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.
@@ -105,7 +105,7 @@ function createCallbackServer(port = 0, expectedState = null, timeoutMs = 300000
105
105
  <!DOCTYPE html>
106
106
  <html>
107
107
  <head>
108
- <title>Authentication Failed</title>
108
+ <title>Authentication failed</title>
109
109
  <style>
110
110
  body { font-family: system-ui, -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
111
111
  .error { background: #fee; border: 1px solid #fcc; padding: 20px; border-radius: 8px; }
@@ -115,7 +115,7 @@ function createCallbackServer(port = 0, expectedState = null, timeoutMs = 300000
115
115
  </head>
116
116
  <body>
117
117
  <div class="error">
118
- <h1>Authentication Failed</h1>
118
+ <h1>Authentication failed</h1>
119
119
  <p><strong>Error:</strong> ${escapeHtml(error)}</p>
120
120
  ${errorDescription ? `<p><strong>Description:</strong> ${escapeHtml(errorDescription)}</p>` : ""}
121
121
  <p>You can close this window and return to your terminal.</p>
@@ -136,7 +136,7 @@ function createCallbackServer(port = 0, expectedState = null, timeoutMs = 300000
136
136
  <!DOCTYPE html>
137
137
  <html>
138
138
  <head>
139
- <title>Authentication Failed</title>
139
+ <title>Authentication failed</title>
140
140
  <style>
141
141
  body { font-family: system-ui, -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
142
142
  .error { background: #fee; border: 1px solid #fcc; padding: 20px; border-radius: 8px; }
@@ -145,7 +145,7 @@ function createCallbackServer(port = 0, expectedState = null, timeoutMs = 300000
145
145
  </head>
146
146
  <body>
147
147
  <div class="error">
148
- <h1>Authentication Failed</h1>
148
+ <h1>Authentication failed</h1>
149
149
  <p>Missing required parameters (code or state).</p>
150
150
  <p>You can close this window and return to your terminal.</p>
151
151
  </div>
@@ -163,7 +163,7 @@ function createCallbackServer(port = 0, expectedState = null, timeoutMs = 300000
163
163
  <!DOCTYPE html>
164
164
  <html>
165
165
  <head>
166
- <title>Authentication Failed</title>
166
+ <title>Authentication failed</title>
167
167
  <style>
168
168
  body { font-family: system-ui, -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
169
169
  .error { background: #fee; border: 1px solid #fcc; padding: 20px; border-radius: 8px; }
@@ -172,7 +172,7 @@ function createCallbackServer(port = 0, expectedState = null, timeoutMs = 300000
172
172
  </head>
173
173
  <body>
174
174
  <div class="error">
175
- <h1>Authentication Failed</h1>
175
+ <h1>Authentication failed</h1>
176
176
  <p>Invalid state parameter (possible CSRF attack).</p>
177
177
  <p>You can close this window and return to your terminal.</p>
178
178
  </div>
@@ -193,7 +193,7 @@ function createCallbackServer(port = 0, expectedState = null, timeoutMs = 300000
193
193
  <!DOCTYPE html>
194
194
  <html>
195
195
  <head>
196
- <title>Authentication Successful</title>
196
+ <title>Authentication successful</title>
197
197
  <style>
198
198
  body { font-family: system-ui, -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
199
199
  .success { background: #efe; border: 1px solid #cfc; padding: 20px; border-radius: 8px; }
@@ -202,7 +202,7 @@ function createCallbackServer(port = 0, expectedState = null, timeoutMs = 300000
202
202
  </head>
203
203
  <body>
204
204
  <div class="success">
205
- <h1>Authentication Successful</h1>
205
+ <h1>Authentication successful</h1>
206
206
  <p>You have successfully authenticated the PostgresAI CLI.</p>
207
207
  <p>You can close this window and return to your terminal.</p>
208
208
  </div>
@@ -0,0 +1,7 @@
1
+ export interface FetchIssuesParams {
2
+ apiKey: string;
3
+ apiBaseUrl: string;
4
+ debug?: boolean;
5
+ }
6
+ export declare function fetchIssues(params: FetchIssuesParams): Promise<unknown>;
7
+ //# sourceMappingURL=issues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issues.d.ts","sourceRoot":"","sources":["../../lib/issues.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CAsE7E"}
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.fetchIssues = fetchIssues;
37
+ const https = __importStar(require("https"));
38
+ const url_1 = require("url");
39
+ const util_1 = require("./util");
40
+ async function fetchIssues(params) {
41
+ const { apiKey, apiBaseUrl, debug } = params;
42
+ if (!apiKey) {
43
+ throw new Error("API key is required");
44
+ }
45
+ const base = (0, util_1.normalizeBaseUrl)(apiBaseUrl);
46
+ const url = new url_1.URL(`${base}/issues`);
47
+ const headers = {
48
+ "access-token": apiKey,
49
+ "Prefer": "return=representation",
50
+ "Content-Type": "application/json",
51
+ };
52
+ if (debug) {
53
+ const debugHeaders = { ...headers, "access-token": (0, util_1.maskSecret)(apiKey) };
54
+ // eslint-disable-next-line no-console
55
+ console.log(`Debug: Resolved API base URL: ${base}`);
56
+ // eslint-disable-next-line no-console
57
+ console.log(`Debug: GET URL: ${url.toString()}`);
58
+ // eslint-disable-next-line no-console
59
+ console.log(`Debug: Auth scheme: access-token`);
60
+ // eslint-disable-next-line no-console
61
+ console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
62
+ }
63
+ return new Promise((resolve, reject) => {
64
+ const req = https.request(url, {
65
+ method: "GET",
66
+ headers,
67
+ }, (res) => {
68
+ let data = "";
69
+ res.on("data", (chunk) => (data += chunk));
70
+ res.on("end", () => {
71
+ if (debug) {
72
+ // eslint-disable-next-line no-console
73
+ console.log(`Debug: Response status: ${res.statusCode}`);
74
+ // eslint-disable-next-line no-console
75
+ console.log(`Debug: Response headers: ${JSON.stringify(res.headers)}`);
76
+ }
77
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
78
+ try {
79
+ const parsed = JSON.parse(data);
80
+ resolve(parsed);
81
+ }
82
+ catch {
83
+ resolve(data);
84
+ }
85
+ }
86
+ else {
87
+ let errMsg = `Failed to fetch issues: HTTP ${res.statusCode}`;
88
+ if (data) {
89
+ try {
90
+ const errObj = JSON.parse(data);
91
+ errMsg += `\n${JSON.stringify(errObj, null, 2)}`;
92
+ }
93
+ catch {
94
+ errMsg += `\n${data}`;
95
+ }
96
+ }
97
+ reject(new Error(errMsg));
98
+ }
99
+ });
100
+ });
101
+ req.on("error", (err) => reject(err));
102
+ req.end();
103
+ });
104
+ }
105
+ //# sourceMappingURL=issues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issues.js","sourceRoot":"","sources":["../../lib/issues.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ interface RootOptsLike {
2
+ apiKey?: string;
3
+ apiBaseUrl?: string;
4
+ }
5
+ export declare function startMcpServer(rootOpts?: RootOptsLike, extra?: {
6
+ debug?: boolean;
7
+ }): Promise<void>;
8
+ export {};
9
+ //# sourceMappingURL=mcp-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../lib/mcp-server.ts"],"names":[],"mappings":"AAUA,UAAU,YAAY;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,cAAc,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgFxG"}
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.startMcpServer = startMcpServer;
37
+ const pkg = __importStar(require("../package.json"));
38
+ const config = __importStar(require("./config"));
39
+ const issues_1 = require("./issues");
40
+ const util_1 = require("./util");
41
+ // MCP SDK imports
42
+ const server_1 = require("@modelcontextprotocol/sdk/server");
43
+ const path = __importStar(require("path"));
44
+ async function startMcpServer(rootOpts, extra) {
45
+ // Resolve stdio transport at runtime to avoid subpath export resolution issues
46
+ const serverEntry = require.resolve("@modelcontextprotocol/sdk/server");
47
+ const stdioPath = path.join(path.dirname(serverEntry), "stdio.js");
48
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
49
+ const { StdioServerTransport } = require(stdioPath);
50
+ // Load schemas dynamically to avoid subpath export resolution issues
51
+ const typesPath = path.resolve(path.dirname(serverEntry), "../types.js");
52
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
53
+ const { CallToolRequestSchema, ListToolsRequestSchema } = require(typesPath);
54
+ const server = new server_1.Server({ name: "postgresai-mcp", version: pkg.version }, { capabilities: { tools: {} } });
55
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
56
+ return {
57
+ tools: [
58
+ {
59
+ name: "list_issues",
60
+ description: "List issues from PostgresAI API (same as CLI 'issues list')",
61
+ inputSchema: {
62
+ type: "object",
63
+ properties: {
64
+ debug: { type: "boolean", description: "Enable verbose debug logs" },
65
+ },
66
+ additionalProperties: false,
67
+ },
68
+ },
69
+ ],
70
+ };
71
+ });
72
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
73
+ const toolName = req.params.name;
74
+ const args = req.params.arguments || {};
75
+ if (toolName !== "list_issues") {
76
+ throw new Error(`Unknown tool: ${toolName}`);
77
+ }
78
+ const cfg = config.readConfig();
79
+ const apiKey = (rootOpts?.apiKey || process.env.PGAI_API_KEY || cfg.apiKey || "").toString();
80
+ const { apiBaseUrl } = (0, util_1.resolveBaseUrls)(rootOpts, cfg);
81
+ const debug = Boolean(args.debug ?? extra?.debug);
82
+ if (!apiKey) {
83
+ return {
84
+ content: [
85
+ {
86
+ type: "text",
87
+ text: "API key is required. Run 'pgai auth' or set PGAI_API_KEY.",
88
+ },
89
+ ],
90
+ isError: true,
91
+ };
92
+ }
93
+ try {
94
+ const result = await (0, issues_1.fetchIssues)({ apiKey, apiBaseUrl, debug });
95
+ return {
96
+ content: [
97
+ { type: "text", text: JSON.stringify(result, null, 2) },
98
+ ],
99
+ };
100
+ }
101
+ catch (err) {
102
+ const message = err instanceof Error ? err.message : String(err);
103
+ return {
104
+ content: [
105
+ { type: "text", text: message },
106
+ ],
107
+ isError: true,
108
+ };
109
+ }
110
+ });
111
+ const transport = new StdioServerTransport();
112
+ await server.connect(transport);
113
+ }
114
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../lib/mcp-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export declare function maskSecret(secret: string): string;
2
+ export interface RootOptsLike {
3
+ apiBaseUrl?: string;
4
+ uiBaseUrl?: string;
5
+ }
6
+ export interface ConfigLike {
7
+ baseUrl?: string | null;
8
+ }
9
+ export interface ResolvedBaseUrls {
10
+ apiBaseUrl: string;
11
+ uiBaseUrl: string;
12
+ }
13
+ /**
14
+ * Normalize a base URL by trimming a single trailing slash and validating.
15
+ * @throws Error if the URL is invalid
16
+ */
17
+ export declare function normalizeBaseUrl(value: string): string;
18
+ /**
19
+ * Resolve API and UI base URLs using precedence and normalize them.
20
+ * Precedence (API): opts.apiBaseUrl → env.PGAI_API_BASE_URL → cfg.baseUrl → default
21
+ * Precedence (UI): opts.uiBaseUrl → env.PGAI_UI_BASE_URL → default
22
+ */
23
+ export declare function resolveBaseUrls(opts?: RootOptsLike, cfg?: ConfigLike, defaults?: {
24
+ apiBaseUrl?: string;
25
+ uiBaseUrl?: string;
26
+ }): ResolvedBaseUrls;
27
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../lib/util.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKjD;AAGD,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUtD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,IAAI,CAAC,EAAE,YAAY,EACnB,GAAG,CAAC,EAAE,UAAU,EAChB,QAAQ,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACzD,gBAAgB,CAWlB"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.maskSecret = maskSecret;
4
+ exports.normalizeBaseUrl = normalizeBaseUrl;
5
+ exports.resolveBaseUrls = resolveBaseUrls;
6
+ function maskSecret(secret) {
7
+ if (!secret)
8
+ return "";
9
+ if (secret.length <= 8)
10
+ return "****";
11
+ if (secret.length <= 16)
12
+ return `${secret.slice(0, 4)}${"*".repeat(secret.length - 8)}${secret.slice(-4)}`;
13
+ return `${secret.slice(0, Math.min(12, secret.length - 8))}${"*".repeat(Math.max(4, secret.length - 16))}${secret.slice(-4)}`;
14
+ }
15
+ /**
16
+ * Normalize a base URL by trimming a single trailing slash and validating.
17
+ * @throws Error if the URL is invalid
18
+ */
19
+ function normalizeBaseUrl(value) {
20
+ const trimmed = (value || "").replace(/\/$/, "");
21
+ try {
22
+ // Validate
23
+ // eslint-disable-next-line no-new
24
+ new URL(trimmed);
25
+ }
26
+ catch {
27
+ throw new Error(`Invalid base URL: ${value}`);
28
+ }
29
+ return trimmed;
30
+ }
31
+ /**
32
+ * Resolve API and UI base URLs using precedence and normalize them.
33
+ * Precedence (API): opts.apiBaseUrl → env.PGAI_API_BASE_URL → cfg.baseUrl → default
34
+ * Precedence (UI): opts.uiBaseUrl → env.PGAI_UI_BASE_URL → default
35
+ */
36
+ function resolveBaseUrls(opts, cfg, defaults = {}) {
37
+ const defApi = defaults.apiBaseUrl || "https://postgres.ai/api/general/";
38
+ const defUi = defaults.uiBaseUrl || "https://console.postgres.ai";
39
+ const apiCandidate = (opts?.apiBaseUrl || process.env.PGAI_API_BASE_URL || cfg?.baseUrl || defApi);
40
+ const uiCandidate = (opts?.uiBaseUrl || process.env.PGAI_UI_BASE_URL || defUi);
41
+ return {
42
+ apiBaseUrl: normalizeBaseUrl(apiCandidate),
43
+ uiBaseUrl: normalizeBaseUrl(uiCandidate),
44
+ };
45
+ }
46
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../lib/util.ts"],"names":[],"mappings":";;AAAA,gCAKC;AAqBD,4CAUC;AAOD,0CAeC;AA1DD,SAAgB,UAAU,CAAC,MAAc;IACvC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IACtC,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE;QAAE,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3G,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAChI,CAAC;AAiBD;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,KAAa;IAC5C,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACjD,IAAI,CAAC;QACH,WAAW;QACX,kCAAkC;QAClC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,qBAAqB,KAAK,EAAE,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,SAAgB,eAAe,CAC7B,IAAmB,EACnB,GAAgB,EAChB,WAAwD,EAAE;IAE1D,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,IAAI,kCAAkC,CAAC;IACzE,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,IAAI,6BAA6B,CAAC;IAElE,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,GAAG,EAAE,OAAO,IAAI,MAAM,CAAW,CAAC;IAC7G,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,KAAK,CAAW,CAAC;IAEzF,OAAO;QACL,UAAU,EAAE,gBAAgB,CAAC,YAAY,CAAC;QAC1C,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC;KACzC,CAAC;AACJ,CAAC"}
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "postgresai",
3
- "version": "0.11.0-alpha.12",
3
+ "version": "0.11.0-alpha.13",
4
4
  "description": "postgres_ai CLI (Node.js)",
5
5
  "license": "Apache-2.0",
6
6
  "private": false,
@@ -29,7 +29,8 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "commander": "^12.1.0",
32
- "js-yaml": "^4.1.0"
32
+ "js-yaml": "^4.1.0",
33
+ "@modelcontextprotocol/sdk": "^1.20.2"
33
34
  },
34
35
  "devDependencies": {
35
36
  "@types/js-yaml": "^4.0.9",
@@ -97,7 +97,7 @@ export function createCallbackServer(
97
97
  <!DOCTYPE html>
98
98
  <html>
99
99
  <head>
100
- <title>Authentication Failed</title>
100
+ <title>Authentication failed</title>
101
101
  <style>
102
102
  body { font-family: system-ui, -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
103
103
  .error { background: #fee; border: 1px solid #fcc; padding: 20px; border-radius: 8px; }
@@ -107,7 +107,7 @@ export function createCallbackServer(
107
107
  </head>
108
108
  <body>
109
109
  <div class="error">
110
- <h1>Authentication Failed</h1>
110
+ <h1>Authentication failed</h1>
111
111
  <p><strong>Error:</strong> ${escapeHtml(error)}</p>
112
112
  ${errorDescription ? `<p><strong>Description:</strong> ${escapeHtml(errorDescription)}</p>` : ""}
113
113
  <p>You can close this window and return to your terminal.</p>
@@ -130,7 +130,7 @@ export function createCallbackServer(
130
130
  <!DOCTYPE html>
131
131
  <html>
132
132
  <head>
133
- <title>Authentication Failed</title>
133
+ <title>Authentication failed</title>
134
134
  <style>
135
135
  body { font-family: system-ui, -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
136
136
  .error { background: #fee; border: 1px solid #fcc; padding: 20px; border-radius: 8px; }
@@ -139,7 +139,7 @@ export function createCallbackServer(
139
139
  </head>
140
140
  <body>
141
141
  <div class="error">
142
- <h1>Authentication Failed</h1>
142
+ <h1>Authentication failed</h1>
143
143
  <p>Missing required parameters (code or state).</p>
144
144
  <p>You can close this window and return to your terminal.</p>
145
145
  </div>
@@ -159,7 +159,7 @@ export function createCallbackServer(
159
159
  <!DOCTYPE html>
160
160
  <html>
161
161
  <head>
162
- <title>Authentication Failed</title>
162
+ <title>Authentication failed</title>
163
163
  <style>
164
164
  body { font-family: system-ui, -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
165
165
  .error { background: #fee; border: 1px solid #fcc; padding: 20px; border-radius: 8px; }
@@ -168,7 +168,7 @@ export function createCallbackServer(
168
168
  </head>
169
169
  <body>
170
170
  <div class="error">
171
- <h1>Authentication Failed</h1>
171
+ <h1>Authentication failed</h1>
172
172
  <p>Invalid state parameter (possible CSRF attack).</p>
173
173
  <p>You can close this window and return to your terminal.</p>
174
174
  </div>
@@ -192,7 +192,7 @@ export function createCallbackServer(
192
192
  <!DOCTYPE html>
193
193
  <html>
194
194
  <head>
195
- <title>Authentication Successful</title>
195
+ <title>Authentication successful</title>
196
196
  <style>
197
197
  body { font-family: system-ui, -apple-system, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
198
198
  .success { background: #efe; border: 1px solid #cfc; padding: 20px; border-radius: 8px; }
@@ -201,7 +201,7 @@ export function createCallbackServer(
201
201
  </head>
202
202
  <body>
203
203
  <div class="success">
204
- <h1>Authentication Successful</h1>
204
+ <h1>Authentication successful</h1>
205
205
  <p>You have successfully authenticated the PostgresAI CLI.</p>
206
206
  <p>You can close this window and return to your terminal.</p>
207
207
  </div>
package/lib/issues.ts ADDED
@@ -0,0 +1,83 @@
1
+ import * as https from "https";
2
+ import { URL } from "url";
3
+ import { maskSecret, normalizeBaseUrl } from "./util";
4
+
5
+ export interface FetchIssuesParams {
6
+ apiKey: string;
7
+ apiBaseUrl: string;
8
+ debug?: boolean;
9
+ }
10
+
11
+ export async function fetchIssues(params: FetchIssuesParams): Promise<unknown> {
12
+ const { apiKey, apiBaseUrl, debug } = params;
13
+ if (!apiKey) {
14
+ throw new Error("API key is required");
15
+ }
16
+
17
+ const base = normalizeBaseUrl(apiBaseUrl);
18
+ const url = new URL(`${base}/issues`);
19
+
20
+ const headers: Record<string, string> = {
21
+ "access-token": apiKey,
22
+ "Prefer": "return=representation",
23
+ "Content-Type": "application/json",
24
+ };
25
+
26
+ if (debug) {
27
+ const debugHeaders: Record<string, string> = { ...headers, "access-token": maskSecret(apiKey) };
28
+ // eslint-disable-next-line no-console
29
+ console.log(`Debug: Resolved API base URL: ${base}`);
30
+ // eslint-disable-next-line no-console
31
+ console.log(`Debug: GET URL: ${url.toString()}`);
32
+ // eslint-disable-next-line no-console
33
+ console.log(`Debug: Auth scheme: access-token`);
34
+ // eslint-disable-next-line no-console
35
+ console.log(`Debug: Request headers: ${JSON.stringify(debugHeaders)}`);
36
+ }
37
+
38
+ return new Promise((resolve, reject) => {
39
+ const req = https.request(
40
+ url,
41
+ {
42
+ method: "GET",
43
+ headers,
44
+ },
45
+ (res) => {
46
+ let data = "";
47
+ res.on("data", (chunk) => (data += chunk));
48
+ res.on("end", () => {
49
+ if (debug) {
50
+ // eslint-disable-next-line no-console
51
+ console.log(`Debug: Response status: ${res.statusCode}`);
52
+ // eslint-disable-next-line no-console
53
+ console.log(`Debug: Response headers: ${JSON.stringify(res.headers)}`);
54
+ }
55
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
56
+ try {
57
+ const parsed = JSON.parse(data);
58
+ resolve(parsed);
59
+ } catch {
60
+ resolve(data);
61
+ }
62
+ } else {
63
+ let errMsg = `Failed to fetch issues: HTTP ${res.statusCode}`;
64
+ if (data) {
65
+ try {
66
+ const errObj = JSON.parse(data);
67
+ errMsg += `\n${JSON.stringify(errObj, null, 2)}`;
68
+ } catch {
69
+ errMsg += `\n${data}`;
70
+ }
71
+ }
72
+ reject(new Error(errMsg));
73
+ }
74
+ });
75
+ }
76
+ );
77
+
78
+ req.on("error", (err: Error) => reject(err));
79
+ req.end();
80
+ });
81
+ }
82
+
83
+