@hellocrossman/mcp-sdk 0.1.2 → 0.2.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 (68) hide show
  1. package/README.md +99 -28
  2. package/dist/cjs/cli.d.ts +3 -0
  3. package/dist/cjs/cli.d.ts.map +1 -0
  4. package/dist/cjs/cli.js +182 -0
  5. package/dist/cjs/cli.js.map +1 -0
  6. package/dist/cjs/db-executor.d.ts +4 -0
  7. package/dist/cjs/db-executor.d.ts.map +1 -0
  8. package/dist/cjs/db-executor.js +152 -0
  9. package/dist/cjs/db-executor.js.map +1 -0
  10. package/dist/cjs/db-introspect.d.ts +18 -0
  11. package/dist/cjs/db-introspect.d.ts.map +1 -0
  12. package/dist/cjs/db-introspect.js +145 -0
  13. package/dist/cjs/db-introspect.js.map +1 -0
  14. package/dist/cjs/db-tool-generator.d.ts +9 -0
  15. package/dist/cjs/db-tool-generator.d.ts.map +1 -0
  16. package/dist/cjs/db-tool-generator.js +167 -0
  17. package/dist/cjs/db-tool-generator.js.map +1 -0
  18. package/dist/cjs/enrichment.d.ts +13 -0
  19. package/dist/cjs/enrichment.d.ts.map +1 -0
  20. package/dist/cjs/enrichment.js +36 -0
  21. package/dist/cjs/enrichment.js.map +1 -0
  22. package/dist/cjs/index.d.ts +2 -0
  23. package/dist/cjs/index.d.ts.map +1 -1
  24. package/dist/cjs/index.js +4 -1
  25. package/dist/cjs/index.js.map +1 -1
  26. package/dist/cjs/introspect.d.ts.map +1 -1
  27. package/dist/cjs/introspect.js +10 -4
  28. package/dist/cjs/introspect.js.map +1 -1
  29. package/dist/cjs/server.d.ts +1 -0
  30. package/dist/cjs/server.d.ts.map +1 -1
  31. package/dist/cjs/server.js +113 -15
  32. package/dist/cjs/server.js.map +1 -1
  33. package/dist/cjs/types.d.ts +6 -0
  34. package/dist/cjs/types.d.ts.map +1 -1
  35. package/dist/cli.d.ts +3 -0
  36. package/dist/cli.d.ts.map +1 -0
  37. package/dist/cli.js +177 -0
  38. package/dist/cli.js.map +1 -0
  39. package/dist/db-executor.d.ts +4 -0
  40. package/dist/db-executor.d.ts.map +1 -0
  41. package/dist/db-executor.js +125 -0
  42. package/dist/db-executor.js.map +1 -0
  43. package/dist/db-introspect.d.ts +18 -0
  44. package/dist/db-introspect.d.ts.map +1 -0
  45. package/dist/db-introspect.js +118 -0
  46. package/dist/db-introspect.js.map +1 -0
  47. package/dist/db-tool-generator.d.ts +9 -0
  48. package/dist/db-tool-generator.d.ts.map +1 -0
  49. package/dist/db-tool-generator.js +163 -0
  50. package/dist/db-tool-generator.js.map +1 -0
  51. package/dist/enrichment.d.ts +13 -0
  52. package/dist/enrichment.d.ts.map +1 -0
  53. package/dist/enrichment.js +33 -0
  54. package/dist/enrichment.js.map +1 -0
  55. package/dist/index.d.ts +2 -0
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +1 -0
  58. package/dist/index.js.map +1 -1
  59. package/dist/introspect.d.ts.map +1 -1
  60. package/dist/introspect.js +10 -4
  61. package/dist/introspect.js.map +1 -1
  62. package/dist/server.d.ts +1 -0
  63. package/dist/server.d.ts.map +1 -1
  64. package/dist/server.js +113 -15
  65. package/dist/server.js.map +1 -1
  66. package/dist/types.d.ts +6 -0
  67. package/dist/types.d.ts.map +1 -1
  68. package/package.json +13 -3
@@ -0,0 +1,118 @@
1
+ const DB_ENV_KEYS = [
2
+ "DATABASE_URL",
3
+ "DB_URL",
4
+ "POSTGRES_URL",
5
+ "PG_CONNECTION_STRING",
6
+ "PGDATABASE",
7
+ ];
8
+ export function detectDatabaseUrl() {
9
+ for (const key of DB_ENV_KEYS) {
10
+ const val = process.env[key];
11
+ if (val && val.length > 0) {
12
+ return val;
13
+ }
14
+ }
15
+ if (process.env.PGHOST && process.env.PGDATABASE) {
16
+ const host = process.env.PGHOST;
17
+ const port = process.env.PGPORT || "5432";
18
+ const db = process.env.PGDATABASE;
19
+ const user = process.env.PGUSER || "postgres";
20
+ const pass = process.env.PGPASSWORD || "";
21
+ return `postgresql://${user}:${pass}@${host}:${port}/${db}`;
22
+ }
23
+ return null;
24
+ }
25
+ function mapPgType(pgType) {
26
+ const t = pgType.toLowerCase();
27
+ if (t.includes("int") ||
28
+ t === "serial" ||
29
+ t === "bigserial" ||
30
+ t === "smallserial" ||
31
+ t === "numeric" ||
32
+ t === "decimal" ||
33
+ t === "real" ||
34
+ t === "double precision" ||
35
+ t === "float") {
36
+ return "number";
37
+ }
38
+ if (t === "boolean" || t === "bool") {
39
+ return "boolean";
40
+ }
41
+ if (t === "jsonb" || t === "json") {
42
+ return "object";
43
+ }
44
+ if (t.includes("timestamp") || t === "date") {
45
+ return "string";
46
+ }
47
+ if (t === "uuid") {
48
+ return "string";
49
+ }
50
+ if (t.startsWith("_") || t.includes("[]")) {
51
+ return "array";
52
+ }
53
+ return "string";
54
+ }
55
+ export async function introspectDatabase(connectionUrl) {
56
+ let pg;
57
+ try {
58
+ pg = await import("pg");
59
+ }
60
+ catch {
61
+ throw new Error("[mcp-sdk] 'pg' package is required for database introspection. Install it with: npm install pg");
62
+ }
63
+ const Pool = pg.default?.Pool || pg.Pool;
64
+ const pool = new Pool({
65
+ connectionString: connectionUrl,
66
+ max: 2,
67
+ connectionTimeoutMillis: 5000,
68
+ idleTimeoutMillis: 10000,
69
+ });
70
+ try {
71
+ const tablesResult = await pool.query(`
72
+ SELECT table_name
73
+ FROM information_schema.tables
74
+ WHERE table_schema = 'public'
75
+ AND table_type = 'BASE TABLE'
76
+ ORDER BY table_name
77
+ `);
78
+ const tables = [];
79
+ for (const row of tablesResult.rows) {
80
+ const tableName = row.table_name;
81
+ const colsResult = await pool.query(`
82
+ SELECT
83
+ c.column_name,
84
+ c.data_type,
85
+ c.udt_name,
86
+ c.is_nullable,
87
+ c.column_default,
88
+ CASE WHEN pk.column_name IS NOT NULL THEN true ELSE false END as is_primary
89
+ FROM information_schema.columns c
90
+ LEFT JOIN (
91
+ SELECT ku.column_name
92
+ FROM information_schema.table_constraints tc
93
+ JOIN information_schema.key_column_usage ku
94
+ ON tc.constraint_name = ku.constraint_name
95
+ WHERE tc.table_name = $1
96
+ AND tc.constraint_type = 'PRIMARY KEY'
97
+ AND tc.table_schema = 'public'
98
+ ) pk ON pk.column_name = c.column_name
99
+ WHERE c.table_name = $1
100
+ AND c.table_schema = 'public'
101
+ ORDER BY c.ordinal_position
102
+ `, [tableName]);
103
+ const columns = colsResult.rows.map((col) => ({
104
+ name: col.column_name,
105
+ type: mapPgType(col.udt_name || col.data_type),
106
+ nullable: col.is_nullable === "YES",
107
+ isPrimary: col.is_primary,
108
+ hasDefault: col.column_default !== null,
109
+ }));
110
+ tables.push({ name: tableName, columns });
111
+ }
112
+ return { tables, connectionSource: "auto-detected" };
113
+ }
114
+ finally {
115
+ await pool.end();
116
+ }
117
+ }
118
+ //# sourceMappingURL=db-introspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-introspect.js","sourceRoot":"","sources":["../src/db-introspect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { DbTable } from "./db-introspect.js";
2
+ import type { DiscoveredTool } from "./types.js";
3
+ export declare function isSensitiveTable(tableName: string): boolean;
4
+ export declare function generateToolsFromTables(tables: DbTable[], options?: {
5
+ excludeTables?: string[];
6
+ includeTables?: string[];
7
+ includeWrites?: boolean;
8
+ }): DiscoveredTool[];
9
+ //# sourceMappingURL=db-tool-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-tool-generator.d.ts","sourceRoot":"","sources":["../src/db-tool-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAkDjD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAG3D;AA2DD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,OAAO,EAAE,EACjB,OAAO,GAAE;IACP,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;CACpB,GACL,cAAc,EAAE,CA0ElB"}
@@ -0,0 +1,163 @@
1
+ const SENSITIVE_TABLES = [
2
+ "users",
3
+ "user",
4
+ "accounts",
5
+ "account",
6
+ "sessions",
7
+ "session",
8
+ "passwords",
9
+ "password_resets",
10
+ "tokens",
11
+ "access_tokens",
12
+ "refresh_tokens",
13
+ "api_keys",
14
+ "secrets",
15
+ "credentials",
16
+ "auth",
17
+ "authentication",
18
+ "oauth",
19
+ "oauth_tokens",
20
+ "migrations",
21
+ "schema_migrations",
22
+ "drizzle",
23
+ "__drizzle_migrations",
24
+ "knex_migrations",
25
+ "knex_migrations_lock",
26
+ "typeorm_metadata",
27
+ "prisma_migrations",
28
+ "_prisma_migrations",
29
+ "pgmigrations",
30
+ ];
31
+ const SENSITIVE_COLUMNS = [
32
+ "password",
33
+ "password_hash",
34
+ "hashed_password",
35
+ "secret",
36
+ "api_key",
37
+ "api_secret",
38
+ "token",
39
+ "access_token",
40
+ "refresh_token",
41
+ "private_key",
42
+ "ssn",
43
+ "social_security",
44
+ "credit_card",
45
+ "card_number",
46
+ ];
47
+ export function isSensitiveTable(tableName) {
48
+ const lower = tableName.toLowerCase();
49
+ return SENSITIVE_TABLES.includes(lower);
50
+ }
51
+ function filterSensitiveColumns(columns) {
52
+ return columns.filter((col) => !SENSITIVE_COLUMNS.includes(col.name.toLowerCase()));
53
+ }
54
+ function formatTableName(name) {
55
+ return name
56
+ .replace(/_/g, " ")
57
+ .replace(/([a-z])([A-Z])/g, "$1 $2")
58
+ .toLowerCase();
59
+ }
60
+ function buildInputSchema(columns, mode) {
61
+ const properties = {};
62
+ const required = [];
63
+ if (mode === "get_by_id") {
64
+ const pk = columns.find((c) => c.isPrimary);
65
+ if (pk) {
66
+ properties[pk.name] = {
67
+ type: pk.type === "number" ? "number" : "string",
68
+ description: `The ${pk.name} of the record`,
69
+ };
70
+ required.push(pk.name);
71
+ }
72
+ }
73
+ else {
74
+ properties["limit"] = {
75
+ type: "number",
76
+ description: "Maximum number of results to return (default: 50)",
77
+ };
78
+ properties["offset"] = {
79
+ type: "number",
80
+ description: "Number of results to skip for pagination",
81
+ };
82
+ const filterableCols = columns.filter((c) => !c.isPrimary && (c.type === "string" || c.type === "number" || c.type === "boolean"));
83
+ for (const col of filterableCols.slice(0, 5)) {
84
+ properties[`filter_${col.name}`] = {
85
+ type: col.type,
86
+ description: `Filter by ${col.name.replace(/_/g, " ")}`,
87
+ };
88
+ }
89
+ }
90
+ return {
91
+ type: "object",
92
+ properties,
93
+ required: required.length > 0 ? required : undefined,
94
+ };
95
+ }
96
+ export function generateToolsFromTables(tables, options = {}) {
97
+ const tools = [];
98
+ for (const table of tables) {
99
+ if (options.includeTables && options.includeTables.length > 0) {
100
+ if (!options.includeTables.includes(table.name))
101
+ continue;
102
+ }
103
+ else {
104
+ if (isSensitiveTable(table.name))
105
+ continue;
106
+ if (options.excludeTables &&
107
+ options.excludeTables.includes(table.name))
108
+ continue;
109
+ }
110
+ const safeColumns = filterSensitiveColumns(table.columns);
111
+ const pk = table.columns.find((c) => c.isPrimary);
112
+ const readableName = formatTableName(table.name);
113
+ tools.push({
114
+ name: `list_${table.name}`,
115
+ description: `List all ${readableName} records with optional filtering and pagination`,
116
+ method: "DB_QUERY",
117
+ path: `db://${table.name}`,
118
+ inputSchema: buildInputSchema(safeColumns, "list"),
119
+ params: [],
120
+ dbOperation: "list",
121
+ });
122
+ if (pk) {
123
+ tools.push({
124
+ name: `get_${table.name}_by_${pk.name}`,
125
+ description: `Get a specific ${readableName} record by its ${pk.name}`,
126
+ method: "DB_QUERY",
127
+ path: `db://${table.name}/${pk.name}`,
128
+ inputSchema: buildInputSchema(safeColumns, "get_by_id"),
129
+ params: [pk.name],
130
+ dbOperation: "get_by_id",
131
+ });
132
+ }
133
+ if (options.includeWrites) {
134
+ const insertCols = safeColumns.filter((c) => !c.isPrimary && !c.hasDefault);
135
+ const insertProps = {};
136
+ const insertRequired = [];
137
+ for (const col of insertCols) {
138
+ insertProps[col.name] = {
139
+ type: col.type,
140
+ description: `The ${col.name.replace(/_/g, " ")} value`,
141
+ };
142
+ if (!col.nullable) {
143
+ insertRequired.push(col.name);
144
+ }
145
+ }
146
+ tools.push({
147
+ name: `create_${table.name}`,
148
+ description: `Create a new ${readableName} record`,
149
+ method: "DB_INSERT",
150
+ path: `db://${table.name}`,
151
+ inputSchema: {
152
+ type: "object",
153
+ properties: insertProps,
154
+ required: insertRequired.length > 0 ? insertRequired : undefined,
155
+ },
156
+ params: [],
157
+ dbOperation: "insert",
158
+ });
159
+ }
160
+ }
161
+ return tools;
162
+ }
163
+ //# sourceMappingURL=db-tool-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-tool-generator.js","sourceRoot":"","sources":["../src/db-tool-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { DiscoveredTool } from "./types.js";
2
+ interface EnrichmentOptions {
3
+ name?: string;
4
+ description?: string;
5
+ endpoint?: string;
6
+ }
7
+ interface EnrichedTool {
8
+ name?: string;
9
+ description?: string;
10
+ }
11
+ export declare function enrichTools(tools: DiscoveredTool[], options?: EnrichmentOptions): Promise<EnrichedTool[]>;
12
+ export {};
13
+ //# sourceMappingURL=enrichment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrichment.d.ts","sourceRoot":"","sources":["../src/enrichment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD,UAAU,iBAAiB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,WAAW,CAC/B,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,YAAY,EAAE,CAAC,CAkCzB"}
@@ -0,0 +1,33 @@
1
+ const DEFAULT_ENRICHMENT_URL = "https://mcp-skill-scanner.replit.app/api/enrich";
2
+ export async function enrichTools(tools, options = {}) {
3
+ const endpoint = options.endpoint || DEFAULT_ENRICHMENT_URL;
4
+ const toolSummaries = tools.map((t) => ({
5
+ name: t.name,
6
+ description: t.description,
7
+ method: t.method,
8
+ path: t.path,
9
+ }));
10
+ const controller = new AbortController();
11
+ const timeout = setTimeout(() => controller.abort(), 15000);
12
+ try {
13
+ const res = await fetch(endpoint, {
14
+ method: "POST",
15
+ headers: { "Content-Type": "application/json" },
16
+ body: JSON.stringify({
17
+ serverName: options.name,
18
+ serverDescription: options.description,
19
+ tools: toolSummaries,
20
+ }),
21
+ signal: controller.signal,
22
+ });
23
+ if (!res.ok) {
24
+ throw new Error(`Enrichment API returned ${res.status}`);
25
+ }
26
+ const data = (await res.json());
27
+ return data.tools || [];
28
+ }
29
+ finally {
30
+ clearTimeout(timeout);
31
+ }
32
+ }
33
+ //# sourceMappingURL=enrichment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrichment.js","sourceRoot":"","sources":["../src/enrichment.ts"],"names":[],"mappings":"AAEA,MAAM,sBAAsB,GAAG,iDAAiD,CAAC;AAajF,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAuB,EACvB,UAA6B,EAAE;IAE/B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,sBAAsB,CAAC;IAE5D,MAAM,aAAa,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACtC,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,IAAI,EAAE,CAAC,CAAC,IAAI;KACb,CAAC,CAAC,CAAC;IAEJ,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;IAE5D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;YAChC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,UAAU,EAAE,OAAO,CAAC,IAAI;gBACxB,iBAAiB,EAAE,OAAO,CAAC,WAAW;gBACtC,KAAK,EAAE,aAAa;aACrB,CAAC;YACF,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA8B,CAAC;QAC7D,OAAO,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAC1B,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export { createMcpServer } from "./server.js";
2
2
  export type { McpServerOptions, DiscoveredRoute, DiscoveredTool } from "./types.js";
3
+ export { detectDatabaseUrl, introspectDatabase } from "./db-introspect.js";
4
+ export type { DbTable, DbColumn, DbIntrospectionResult } from "./db-introspect.js";
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { createMcpServer } from "./server.js";
2
+ export { detectDatabaseUrl, introspectDatabase } from "./db-introspect.js";
2
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"introspect.d.ts","sourceRoot":"","sources":["../src/introspect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,WAAW,SAAS,GACnB,eAAe,EAAE,CAkEnB"}
1
+ {"version":3,"file":"introspect.d.ts","sourceRoot":"","sources":["../src/introspect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,WAAW,SAAS,GACnB,eAAe,EAAE,CAyEnB"}
@@ -42,16 +42,22 @@ export function introspectExpressRoutes(app, routePrefix = "/api") {
42
42
  }
43
43
  const a = app;
44
44
  let router = null;
45
- if (typeof a.router === "function" && a.router.stack) {
46
- router = a.router;
47
- }
48
- else if (a._router && a._router.stack) {
45
+ if (a._router && a._router.stack) {
49
46
  router = a._router;
50
47
  }
51
48
  else if (typeof a.lazyrouter === "function") {
52
49
  a.lazyrouter();
53
50
  router = a._router;
54
51
  }
52
+ if (!router) {
53
+ try {
54
+ const r = a.router;
55
+ if (r && r.stack) {
56
+ router = r;
57
+ }
58
+ }
59
+ catch (_) { }
60
+ }
55
61
  if (router && router.stack) {
56
62
  extractRoutes(router.stack);
57
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"introspect.js","sourceRoot":"","sources":["../src/introspect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"introspect.js","sourceRoot":"","sources":["../src/introspect.ts"],"names":[],"mappings":"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"}
package/dist/server.d.ts CHANGED
@@ -2,5 +2,6 @@ import type { McpServerOptions, DiscoveredTool } from "./types.js";
2
2
  export declare function createMcpServer(options: McpServerOptions): {
3
3
  readonly tools: DiscoveredTool[];
4
4
  readonly routes: import("./types.js").DiscoveredRoute[];
5
+ ready: Promise<void>;
5
6
  };
6
7
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGnE,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB;;;EA8KxD"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGnE,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB;;;;EAoRxD"}
package/dist/server.js CHANGED
@@ -4,27 +4,110 @@ import { randomUUID } from "crypto";
4
4
  import { introspectExpressRoutes } from "./introspect.js";
5
5
  import { generateToolsFromRoutes } from "./tool-generator.js";
6
6
  import { executeTool } from "./executor.js";
7
+ import { detectDatabaseUrl, introspectDatabase } from "./db-introspect.js";
8
+ import { generateToolsFromTables, isSensitiveTable } from "./db-tool-generator.js";
9
+ import { initDbPool, executeDbTool } from "./db-executor.js";
10
+ import { enrichTools } from "./enrichment.js";
7
11
  import { z } from "zod";
8
12
  export function createMcpServer(options) {
9
- const { app, path: mcpPath = "/mcp", name = "mcp-server", version = "1.0.0", description = "Auto-discovered MCP server", routePrefix = "/api", excludeRoutes = [], } = options;
13
+ const { app, path: mcpPath = "/mcp", name = "mcp-server", version = "1.0.0", description = "Auto-discovered MCP server", routePrefix = "/api", excludeRoutes = [], database = true, excludeTables = [], includeTables = [], includeWrites = false, enrichment = true, } = options;
10
14
  let tools = null;
11
- function discoverTools() {
12
- if (tools)
15
+ let discoveryComplete = false;
16
+ let discoveryPromise = null;
17
+ async function discoverTools() {
18
+ if (tools && discoveryComplete)
13
19
  return tools;
20
+ const allTools = [];
14
21
  const routes = introspectExpressRoutes(app, routePrefix);
15
- tools = generateToolsFromRoutes(routes, excludeRoutes);
16
- console.log(`[mcp-sdk] Discovered ${routes.length} API routes`);
17
- console.log(`[mcp-sdk] Generated ${tools.length} MCP tools:`);
18
- tools.forEach((t) => {
19
- console.log(`[mcp-sdk] - ${t.name} (${t.method} ${t.path})`);
22
+ const routeTools = generateToolsFromRoutes(routes, excludeRoutes);
23
+ allTools.push(...routeTools);
24
+ console.log(`\n[mcp-sdk] ---- Discovery Report ----`);
25
+ console.log(`[mcp-sdk] Express routes: ${routes.length} found, ${routeTools.length} tools generated`);
26
+ routeTools.forEach((t) => {
27
+ console.log(`[mcp-sdk] + ${t.name} (${t.method} ${t.path})`);
20
28
  });
29
+ if (database !== false) {
30
+ const dbUrl = typeof database === "string" ? database : detectDatabaseUrl();
31
+ if (dbUrl) {
32
+ try {
33
+ await initDbPool(dbUrl);
34
+ const dbResult = await introspectDatabase(dbUrl);
35
+ const sensitiveTables = dbResult.tables.filter((t) => isSensitiveTable(t.name));
36
+ const dbTools = generateToolsFromTables(dbResult.tables, {
37
+ excludeTables,
38
+ includeTables,
39
+ includeWrites,
40
+ });
41
+ allTools.push(...dbTools);
42
+ console.log(`[mcp-sdk] Database: ${dbResult.tables.length} tables found, ${dbTools.length} tools generated`);
43
+ dbTools.forEach((t) => {
44
+ console.log(`[mcp-sdk] + ${t.name} (${t.method})`);
45
+ });
46
+ if (sensitiveTables.length > 0) {
47
+ console.log(`[mcp-sdk] Auto-hidden (sensitive): ${sensitiveTables.map((t) => t.name).join(", ")}`);
48
+ }
49
+ }
50
+ catch (err) {
51
+ const msg = err instanceof Error ? err.message : String(err);
52
+ console.log(`[mcp-sdk] Database: skipped (${msg})`);
53
+ }
54
+ }
55
+ else {
56
+ console.log(`[mcp-sdk] Database: no connection found in environment`);
57
+ }
58
+ }
59
+ if (enrichment !== false) {
60
+ const endpoint = typeof enrichment === "string" ? enrichment : undefined;
61
+ try {
62
+ const enriched = await enrichTools(allTools, { name, description, endpoint });
63
+ for (let i = 0; i < allTools.length; i++) {
64
+ if (enriched[i]) {
65
+ if (enriched[i].description)
66
+ allTools[i].description = enriched[i].description;
67
+ if (enriched[i].name)
68
+ allTools[i].name = enriched[i].name;
69
+ }
70
+ }
71
+ console.log(`[mcp-sdk] AI enrichment: applied`);
72
+ }
73
+ catch {
74
+ console.log(`[mcp-sdk] AI enrichment: skipped (service unavailable)`);
75
+ }
76
+ }
77
+ console.log(`[mcp-sdk] Total tools: ${allTools.length}`);
78
+ console.log(`[mcp-sdk] ----------------------------\n`);
79
+ const nameCount = new Map();
80
+ for (const tool of allTools) {
81
+ const count = nameCount.get(tool.name) || 0;
82
+ nameCount.set(tool.name, count + 1);
83
+ }
84
+ const seen = new Map();
85
+ for (const tool of allTools) {
86
+ const total = nameCount.get(tool.name) || 1;
87
+ if (total > 1) {
88
+ const idx = (seen.get(tool.name) || 0) + 1;
89
+ seen.set(tool.name, idx);
90
+ if (idx > 1) {
91
+ tool.name = `${tool.name}_db`;
92
+ }
93
+ }
94
+ }
95
+ tools = allTools;
96
+ discoveryComplete = true;
21
97
  return tools;
22
98
  }
99
+ discoveryPromise = discoverTools().then(() => { }).catch((err) => {
100
+ console.error("[mcp-sdk] Discovery error:", err);
101
+ });
102
+ function getToolsSync() {
103
+ return tools || [];
104
+ }
23
105
  const port = parseInt(process.env.PORT || "5000", 10);
24
106
  const sessions = new Map();
25
- function buildMcpServer() {
107
+ async function buildMcpServer() {
108
+ await discoveryPromise;
26
109
  const mcpServer = new McpServer({ name, version });
27
- const currentTools = discoverTools();
110
+ const currentTools = getToolsSync();
28
111
  for (const tool of currentTools) {
29
112
  const paramShape = {};
30
113
  if (tool.inputSchema.properties && typeof tool.inputSchema.properties === "object") {
@@ -34,9 +117,15 @@ export function createMcpServer(options) {
34
117
  if (schema.type === "number") {
35
118
  zodType = z.number().describe(schema.description || key);
36
119
  }
120
+ else if (schema.type === "boolean") {
121
+ zodType = z.boolean().describe(schema.description || key);
122
+ }
37
123
  else if (schema.type === "object") {
38
124
  zodType = z.record(z.unknown()).describe(schema.description || key);
39
125
  }
126
+ else if (schema.type === "array") {
127
+ zodType = z.array(z.unknown()).describe(schema.description || key);
128
+ }
40
129
  else {
41
130
  zodType = z.string().describe(schema.description || key);
42
131
  }
@@ -46,9 +135,16 @@ export function createMcpServer(options) {
46
135
  paramShape[key] = zodType;
47
136
  }
48
137
  }
138
+ const toolRef = tool;
49
139
  mcpServer.tool(tool.name, tool.description, paramShape, async (args) => {
50
140
  try {
51
- const result = await executeTool(app, tool, args, port);
141
+ let result;
142
+ if (toolRef.method.startsWith("DB_")) {
143
+ result = await executeDbTool(toolRef, args);
144
+ }
145
+ else {
146
+ result = await executeTool(app, toolRef, args, port);
147
+ }
52
148
  return {
53
149
  content: [{ type: "text", text: result }],
54
150
  };
@@ -81,7 +177,7 @@ export function createMcpServer(options) {
81
177
  return;
82
178
  }
83
179
  try {
84
- const mcpServer = buildMcpServer();
180
+ const mcpServer = await buildMcpServer();
85
181
  const transport = new StreamableHTTPServerTransport({
86
182
  sessionIdGenerator: () => randomUUID(),
87
183
  });
@@ -105,7 +201,7 @@ export function createMcpServer(options) {
105
201
  }
106
202
  }
107
203
  });
108
- app.get(mcpPath, (req, res) => {
204
+ app.get(mcpPath, async (req, res) => {
109
205
  const sessionId = req.headers["mcp-session-id"];
110
206
  if (sessionId && sessions.has(sessionId)) {
111
207
  const session = sessions.get(sessionId);
@@ -114,7 +210,8 @@ export function createMcpServer(options) {
114
210
  });
115
211
  return;
116
212
  }
117
- const currentTools = discoverTools();
213
+ await discoveryPromise;
214
+ const currentTools = getToolsSync();
118
215
  res.json({
119
216
  name,
120
217
  version,
@@ -142,8 +239,9 @@ export function createMcpServer(options) {
142
239
  });
143
240
  console.log(`[mcp-sdk] MCP endpoint available at ${mcpPath}`);
144
241
  return {
145
- get tools() { return discoverTools(); },
242
+ get tools() { return getToolsSync(); },
146
243
  get routes() { return introspectExpressRoutes(app, routePrefix); },
244
+ ready: discoveryPromise,
147
245
  };
148
246
  }
149
247
  //# sourceMappingURL=server.js.map