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.
- package/README.md +39 -0
- package/bin/postgres-ai.ts +107 -18
- package/dist/bin/postgres-ai.js +97 -19
- package/dist/bin/postgres-ai.js.map +1 -1
- package/dist/lib/auth-server.js +8 -8
- package/dist/lib/issues.d.ts +7 -0
- package/dist/lib/issues.d.ts.map +1 -0
- package/dist/lib/issues.js +105 -0
- package/dist/lib/issues.js.map +1 -0
- package/dist/lib/mcp-server.d.ts +9 -0
- package/dist/lib/mcp-server.d.ts.map +1 -0
- package/dist/lib/mcp-server.js +114 -0
- package/dist/lib/mcp-server.js.map +1 -0
- package/dist/lib/util.d.ts +27 -0
- package/dist/lib/util.d.ts.map +1 -0
- package/dist/lib/util.js +46 -0
- package/dist/lib/util.js.map +1 -0
- package/dist/package.json +3 -2
- package/lib/auth-server.ts +8 -8
- package/lib/issues.ts +83 -0
- package/lib/mcp-server.ts +98 -0
- package/lib/util.ts +60 -0
- package/package.json +3 -2
- package/tsconfig.json +2 -2
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import * as pkg from "../package.json";
|
|
2
|
+
import * as config from "./config";
|
|
3
|
+
import { fetchIssues } from "./issues";
|
|
4
|
+
import { resolveBaseUrls } from "./util";
|
|
5
|
+
|
|
6
|
+
// MCP SDK imports
|
|
7
|
+
import { Server } from "@modelcontextprotocol/sdk/server";
|
|
8
|
+
import * as path from "path";
|
|
9
|
+
// Types schemas will be loaded dynamically from the SDK's CJS bundle
|
|
10
|
+
|
|
11
|
+
interface RootOptsLike {
|
|
12
|
+
apiKey?: string;
|
|
13
|
+
apiBaseUrl?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function startMcpServer(rootOpts?: RootOptsLike, extra?: { debug?: boolean }): Promise<void> {
|
|
17
|
+
// Resolve stdio transport at runtime to avoid subpath export resolution issues
|
|
18
|
+
const serverEntry = require.resolve("@modelcontextprotocol/sdk/server");
|
|
19
|
+
const stdioPath = path.join(path.dirname(serverEntry), "stdio.js");
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
21
|
+
const { StdioServerTransport } = require(stdioPath);
|
|
22
|
+
// Load schemas dynamically to avoid subpath export resolution issues
|
|
23
|
+
const typesPath = path.resolve(path.dirname(serverEntry), "../types.js");
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
25
|
+
const { CallToolRequestSchema, ListToolsRequestSchema } = require(typesPath);
|
|
26
|
+
|
|
27
|
+
const server = new Server(
|
|
28
|
+
{ name: "postgresai-mcp", version: pkg.version },
|
|
29
|
+
{ capabilities: { tools: {} } }
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
33
|
+
return {
|
|
34
|
+
tools: [
|
|
35
|
+
{
|
|
36
|
+
name: "list_issues",
|
|
37
|
+
description: "List issues from PostgresAI API (same as CLI 'issues list')",
|
|
38
|
+
inputSchema: {
|
|
39
|
+
type: "object",
|
|
40
|
+
properties: {
|
|
41
|
+
debug: { type: "boolean", description: "Enable verbose debug logs" },
|
|
42
|
+
},
|
|
43
|
+
additionalProperties: false,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
server.setRequestHandler(CallToolRequestSchema, async (req: any) => {
|
|
51
|
+
const toolName = req.params.name;
|
|
52
|
+
const args = (req.params.arguments as Record<string, unknown>) || {};
|
|
53
|
+
|
|
54
|
+
if (toolName !== "list_issues") {
|
|
55
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const cfg = config.readConfig();
|
|
59
|
+
const apiKey = (rootOpts?.apiKey || process.env.PGAI_API_KEY || cfg.apiKey || "").toString();
|
|
60
|
+
const { apiBaseUrl } = resolveBaseUrls(rootOpts, cfg);
|
|
61
|
+
|
|
62
|
+
const debug = Boolean(args.debug ?? extra?.debug);
|
|
63
|
+
|
|
64
|
+
if (!apiKey) {
|
|
65
|
+
return {
|
|
66
|
+
content: [
|
|
67
|
+
{
|
|
68
|
+
type: "text",
|
|
69
|
+
text: "API key is required. Run 'pgai auth' or set PGAI_API_KEY.",
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
isError: true,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const result = await fetchIssues({ apiKey, apiBaseUrl, debug });
|
|
78
|
+
return {
|
|
79
|
+
content: [
|
|
80
|
+
{ type: "text", text: JSON.stringify(result, null, 2) },
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
} catch (err) {
|
|
84
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
85
|
+
return {
|
|
86
|
+
content: [
|
|
87
|
+
{ type: "text", text: message },
|
|
88
|
+
],
|
|
89
|
+
isError: true,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const transport = new StdioServerTransport();
|
|
95
|
+
await server.connect(transport);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
package/lib/util.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export function maskSecret(secret: string): string {
|
|
2
|
+
if (!secret) return "";
|
|
3
|
+
if (secret.length <= 8) return "****";
|
|
4
|
+
if (secret.length <= 16) return `${secret.slice(0, 4)}${"*".repeat(secret.length - 8)}${secret.slice(-4)}`;
|
|
5
|
+
return `${secret.slice(0, Math.min(12, secret.length - 8))}${"*".repeat(Math.max(4, secret.length - 16))}${secret.slice(-4)}`;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export interface RootOptsLike {
|
|
10
|
+
apiBaseUrl?: string;
|
|
11
|
+
uiBaseUrl?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ConfigLike {
|
|
15
|
+
baseUrl?: string | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ResolvedBaseUrls {
|
|
19
|
+
apiBaseUrl: string;
|
|
20
|
+
uiBaseUrl: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Normalize a base URL by trimming a single trailing slash and validating.
|
|
25
|
+
* @throws Error if the URL is invalid
|
|
26
|
+
*/
|
|
27
|
+
export function normalizeBaseUrl(value: string): string {
|
|
28
|
+
const trimmed = (value || "").replace(/\/$/, "");
|
|
29
|
+
try {
|
|
30
|
+
// Validate
|
|
31
|
+
// eslint-disable-next-line no-new
|
|
32
|
+
new URL(trimmed);
|
|
33
|
+
} catch {
|
|
34
|
+
throw new Error(`Invalid base URL: ${value}`);
|
|
35
|
+
}
|
|
36
|
+
return trimmed;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Resolve API and UI base URLs using precedence and normalize them.
|
|
41
|
+
* Precedence (API): opts.apiBaseUrl → env.PGAI_API_BASE_URL → cfg.baseUrl → default
|
|
42
|
+
* Precedence (UI): opts.uiBaseUrl → env.PGAI_UI_BASE_URL → default
|
|
43
|
+
*/
|
|
44
|
+
export function resolveBaseUrls(
|
|
45
|
+
opts?: RootOptsLike,
|
|
46
|
+
cfg?: ConfigLike,
|
|
47
|
+
defaults: { apiBaseUrl?: string; uiBaseUrl?: string } = {}
|
|
48
|
+
): ResolvedBaseUrls {
|
|
49
|
+
const defApi = defaults.apiBaseUrl || "https://postgres.ai/api/general/";
|
|
50
|
+
const defUi = defaults.uiBaseUrl || "https://console.postgres.ai";
|
|
51
|
+
|
|
52
|
+
const apiCandidate = (opts?.apiBaseUrl || process.env.PGAI_API_BASE_URL || cfg?.baseUrl || defApi) as string;
|
|
53
|
+
const uiCandidate = (opts?.uiBaseUrl || process.env.PGAI_UI_BASE_URL || defUi) as string;
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
apiBaseUrl: normalizeBaseUrl(apiCandidate),
|
|
57
|
+
uiBaseUrl: normalizeBaseUrl(uiCandidate),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postgresai",
|
|
3
|
-
"version": "0.11.0-alpha.
|
|
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",
|
package/tsconfig.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"target": "ES2020",
|
|
4
|
-
"module": "
|
|
4
|
+
"module": "node16",
|
|
5
5
|
"lib": ["ES2020"],
|
|
6
6
|
"outDir": "./dist",
|
|
7
7
|
"rootDir": "./",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"declaration": true,
|
|
14
14
|
"declarationMap": true,
|
|
15
15
|
"sourceMap": true,
|
|
16
|
-
"moduleResolution": "
|
|
16
|
+
"moduleResolution": "node16",
|
|
17
17
|
"types": ["node"]
|
|
18
18
|
},
|
|
19
19
|
"include": [
|