truss-db-mcp 1.0.0 → 1.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.
- package/.github/FUNDING.yml +1 -0
- package/.github/workflows/mcp-registry-publish.yml +21 -0
- package/.mcpize/project.json +4 -0
- package/README.md +47 -1
- package/agent-card.json +80 -0
- package/dist/lib/billing.d.ts +7 -0
- package/dist/lib/billing.d.ts.map +1 -0
- package/dist/lib/billing.js +31 -0
- package/dist/lib/billing.js.map +1 -0
- package/dist/tools/connect.d.ts.map +1 -1
- package/dist/tools/connect.js +2 -0
- package/dist/tools/connect.js.map +1 -1
- package/dist/tools/describe-table.d.ts.map +1 -1
- package/dist/tools/describe-table.js +2 -0
- package/dist/tools/describe-table.js.map +1 -1
- package/dist/tools/export-data.d.ts.map +1 -1
- package/dist/tools/export-data.js +2 -0
- package/dist/tools/export-data.js.map +1 -1
- package/dist/tools/generate-migration.d.ts.map +1 -1
- package/dist/tools/generate-migration.js +2 -0
- package/dist/tools/generate-migration.js.map +1 -1
- package/dist/tools/list-tables.d.ts.map +1 -1
- package/dist/tools/list-tables.js +2 -0
- package/dist/tools/list-tables.js.map +1 -1
- package/dist/tools/natural-language-query.d.ts.map +1 -1
- package/dist/tools/natural-language-query.js +2 -0
- package/dist/tools/natural-language-query.js.map +1 -1
- package/dist/tools/optimize-query.d.ts.map +1 -1
- package/dist/tools/optimize-query.js +2 -0
- package/dist/tools/optimize-query.js.map +1 -1
- package/dist/tools/query.d.ts.map +1 -1
- package/dist/tools/query.js +2 -0
- package/dist/tools/query.js.map +1 -1
- package/mcpize.yaml +32 -0
- package/package.json +20 -6
- package/server.json +20 -0
- package/src/lib/billing.ts +34 -0
- package/src/tools/connect.ts +2 -0
- package/src/tools/describe-table.ts +2 -0
- package/src/tools/export-data.ts +2 -0
- package/src/tools/generate-migration.ts +2 -0
- package/src/tools/list-tables.ts +2 -0
- package/src/tools/natural-language-query.ts +2 -0
- package/src/tools/optimize-query.ts +2 -0
- package/src/tools/query.ts +2 -0
- package/evals/test.db +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
custom: ["https://claw-factory.github.io/truss-site"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Publish to MCP Registry
|
|
2
|
+
on:
|
|
3
|
+
workflow_dispatch:
|
|
4
|
+
|
|
5
|
+
permissions:
|
|
6
|
+
id-token: write
|
|
7
|
+
contents: read
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
publish:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- name: Install mcp-publisher
|
|
15
|
+
run: npm install -g mcp-publisher
|
|
16
|
+
- name: Login via OIDC
|
|
17
|
+
run: mcp-publisher login github-oidc
|
|
18
|
+
- name: Validate
|
|
19
|
+
run: mcp-publisher validate server.json
|
|
20
|
+
- name: Publish
|
|
21
|
+
run: mcp-publisher publish server.json
|
package/README.md
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
# truss-db-mcp
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/truss-db-mcp)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
3
6
|
Database query MCP server for Claude Code. Connect to SQLite, PostgreSQL, or MySQL databases directly from your AI assistant.
|
|
4
7
|
|
|
5
8
|
## Quick Start
|
|
6
9
|
|
|
10
|
+
Run with npx (no install needed):
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npx -y truss-db-mcp
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Claude Desktop / Claude Code
|
|
17
|
+
|
|
18
|
+
Add to your `claude_desktop_config.json` or `.claude/settings.json`:
|
|
19
|
+
|
|
7
20
|
```json
|
|
8
21
|
{
|
|
9
22
|
"mcpServers": {
|
|
10
|
-
"
|
|
23
|
+
"db-query": {
|
|
11
24
|
"command": "npx",
|
|
12
25
|
"args": ["-y", "truss-db-mcp"]
|
|
13
26
|
}
|
|
@@ -15,6 +28,23 @@ Database query MCP server for Claude Code. Connect to SQLite, PostgreSQL, or MyS
|
|
|
15
28
|
}
|
|
16
29
|
```
|
|
17
30
|
|
|
31
|
+
### Cursor
|
|
32
|
+
|
|
33
|
+
Add to your Cursor MCP settings:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"mcpServers": {
|
|
38
|
+
"db-query": {
|
|
39
|
+
"command": "npx",
|
|
40
|
+
"args": ["-y", "truss-db-mcp"]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
18
48
|
## Free Tier Tools
|
|
19
49
|
|
|
20
50
|
| Tool | Description |
|
|
@@ -67,3 +97,19 @@ Use optimize_query with sql: "SELECT * FROM orders WHERE status = 'pending'"
|
|
|
67
97
|
## License
|
|
68
98
|
|
|
69
99
|
MIT
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## A2A Discovery
|
|
105
|
+
|
|
106
|
+
This server publishes a [Google A2A Protocol](https://a2a-protocol.org) Agent Card, making it discoverable by any A2A-compatible agent framework (LangGraph, CrewAI, Google ADK, AutoGen, and others).
|
|
107
|
+
|
|
108
|
+
**Agent Card:** [`agent-card.json`](./agent-card.json)
|
|
109
|
+
|
|
110
|
+
The agent card describes this server's skills, capabilities, input/output modalities, and authentication requirements in a machine-readable format. A2A clients can use it to discover and invoke tools automatically without manual configuration.
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Fetch the agent card
|
|
114
|
+
curl https://raw.githubusercontent.com/claw-factory/truss-db-mcp/main/agent-card.json
|
|
115
|
+
```
|
package/agent-card.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "TRUSS DB MCP — Natural Language Database Queries",
|
|
3
|
+
"description": "Database query MCP server for AI agents. Connect to SQLite, PostgreSQL, or MySQL databases and query them in natural language. Schema exploration, SQL generation, and query optimization — from your AI assistant.",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"documentationUrl": "https://github.com/claw-factory/truss-db-mcp#readme",
|
|
6
|
+
"provider": {
|
|
7
|
+
"organization": "TRUSS / claw-factory",
|
|
8
|
+
"url": "https://claw-factory.github.io/truss-site"
|
|
9
|
+
},
|
|
10
|
+
"supportedInterfaces": [
|
|
11
|
+
{
|
|
12
|
+
"url": "https://claw-factory.github.io/truss-site/a2a/v1",
|
|
13
|
+
"protocolBinding": "HTTP+JSON",
|
|
14
|
+
"protocolVersion": "1.0"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"capabilities": {
|
|
18
|
+
"streaming": false,
|
|
19
|
+
"pushNotifications": false,
|
|
20
|
+
"stateTransitionHistory": false,
|
|
21
|
+
"extendedAgentCard": false
|
|
22
|
+
},
|
|
23
|
+
"securitySchemes": {
|
|
24
|
+
"bearer": {
|
|
25
|
+
"type": "http",
|
|
26
|
+
"scheme": "bearer",
|
|
27
|
+
"description": "TRUSS license key — required for database connectivity"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"security": [{"bearer": []}],
|
|
31
|
+
"defaultInputModes": ["text/plain", "application/json"],
|
|
32
|
+
"defaultOutputModes": ["application/json"],
|
|
33
|
+
"pricing": {
|
|
34
|
+
"free": false,
|
|
35
|
+
"paid": {
|
|
36
|
+
"amount": 25,
|
|
37
|
+
"currency": "USD",
|
|
38
|
+
"interval": "month",
|
|
39
|
+
"url": "https://claw-factory.github.io/truss-site"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"skills": [
|
|
43
|
+
{
|
|
44
|
+
"id": "db_natural_language_query",
|
|
45
|
+
"name": "Natural Language SQL",
|
|
46
|
+
"description": "Convert natural language questions into SQL queries and execute them against connected databases",
|
|
47
|
+
"tags": ["database", "sql", "natural-language", "nlp"],
|
|
48
|
+
"examples": ["Show me the top 10 customers by revenue this quarter", "How many users signed up last week?"],
|
|
49
|
+
"inputModes": ["text/plain"],
|
|
50
|
+
"outputModes": ["application/json"]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "db_schema_exploration",
|
|
54
|
+
"name": "Schema Exploration",
|
|
55
|
+
"description": "Explore database schema, list tables, inspect column definitions, and understand relationships",
|
|
56
|
+
"tags": ["database", "schema", "exploration"],
|
|
57
|
+
"examples": ["Show me all tables and their relationships in this database"],
|
|
58
|
+
"inputModes": ["application/json"],
|
|
59
|
+
"outputModes": ["application/json"]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"id": "db_query_optimization",
|
|
63
|
+
"name": "Query Optimization",
|
|
64
|
+
"description": "Analyze slow queries, suggest indexes, and rewrite inefficient SQL for better performance",
|
|
65
|
+
"tags": ["database", "performance", "optimization", "sql"],
|
|
66
|
+
"examples": ["Optimize this slow PostgreSQL query that runs for 30 seconds"],
|
|
67
|
+
"inputModes": ["text/plain"],
|
|
68
|
+
"outputModes": ["text/plain", "application/json"]
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"id": "db_execute_query",
|
|
72
|
+
"name": "Execute Query",
|
|
73
|
+
"description": "Execute a raw SQL query against SQLite, PostgreSQL, or MySQL and return structured results",
|
|
74
|
+
"tags": ["database", "sql", "execution"],
|
|
75
|
+
"examples": ["Run SELECT * FROM orders WHERE status = 'pending' LIMIT 100"],
|
|
76
|
+
"inputModes": ["text/plain"],
|
|
77
|
+
"outputModes": ["application/json"]
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Record a tool call for usage-based billing via Stripe Billing Meters.
|
|
3
|
+
* Non-blocking — failures are logged but do not interrupt the tool call.
|
|
4
|
+
* Requires STRIPE_SECRET_KEY and STRIPE_CUSTOMER_ID env vars.
|
|
5
|
+
*/
|
|
6
|
+
export declare function recordToolCall(toolName: string): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=billing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"billing.d.ts","sourceRoot":"","sources":["../../src/lib/billing.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBpE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import Stripe from 'stripe';
|
|
2
|
+
const stripeKey = process.env.STRIPE_SECRET_KEY;
|
|
3
|
+
const customerId = process.env.STRIPE_CUSTOMER_ID;
|
|
4
|
+
let stripe = null;
|
|
5
|
+
if (stripeKey) {
|
|
6
|
+
stripe = new Stripe(stripeKey);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Record a tool call for usage-based billing via Stripe Billing Meters.
|
|
10
|
+
* Non-blocking — failures are logged but do not interrupt the tool call.
|
|
11
|
+
* Requires STRIPE_SECRET_KEY and STRIPE_CUSTOMER_ID env vars.
|
|
12
|
+
*/
|
|
13
|
+
export async function recordToolCall(toolName) {
|
|
14
|
+
if (!stripe || !customerId)
|
|
15
|
+
return;
|
|
16
|
+
try {
|
|
17
|
+
await stripe.billing.meterEvents.create({
|
|
18
|
+
event_name: 'mcp_tool_call',
|
|
19
|
+
payload: {
|
|
20
|
+
stripe_customer_id: customerId,
|
|
21
|
+
value: '1',
|
|
22
|
+
},
|
|
23
|
+
identifier: `${customerId}_${toolName}_${Date.now()}`,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
// Non-blocking — log and continue
|
|
28
|
+
console.error(`[billing] meter event failed for ${toolName}:`, err.message);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=billing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"billing.js","sourceRoot":"","sources":["../../src/lib/billing.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;AAChD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AAElD,IAAI,MAAM,GAAkB,IAAI,CAAC;AAEjC,IAAI,SAAS,EAAE,CAAC;IACd,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB;IACnD,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU;QAAE,OAAO;IAEnC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC;YACtC,UAAU,EAAE,eAAe;YAC3B,OAAO,EAAE;gBACP,kBAAkB,EAAE,UAAU;gBAC9B,KAAK,EAAE,GAAG;aACX;YACD,UAAU,EAAE,GAAG,UAAU,IAAI,QAAQ,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE;SACtD,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,kCAAkC;QAClC,OAAO,CAAC,KAAK,CAAC,oCAAoC,QAAQ,GAAG,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;IACzF,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/tools/connect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/tools/connect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuCvD"}
|
package/dist/tools/connect.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { connectSqlite } from '../lib/connection.js';
|
|
3
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
3
4
|
export function registerConnect(server) {
|
|
4
5
|
server.tool('connect', 'Connect to a SQLite database file. Provide the path to the .db or .sqlite file.', {
|
|
5
6
|
path: z.string().describe('Path to the SQLite database file'),
|
|
6
7
|
}, async ({ path }) => {
|
|
8
|
+
recordToolCall('connect').catch(() => { });
|
|
7
9
|
try {
|
|
8
10
|
const info = connectSqlite(path);
|
|
9
11
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/tools/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/tools/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,UAAU,eAAe,CAAC,MAAiB;IAC/C,MAAM,CAAC,IAAI,CACT,SAAS,EACT,iFAAiF,EACjF;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;KAC9D,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,cAAc,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YAEjC,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,SAAS,EAAE,IAAI,CAAC,SAAS;4BACzB,OAAO,EAAE,IAAI,CAAC,OAAO;4BACrB,MAAM,EAAE,IAAI,CAAC,MAAM;4BACnB,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;4BAC9B,OAAO,EAAE,IAAI,CAAC,OAAO;4BACrB,IAAI,EAAE,IAAI,CAAC,IAAI;yBAChB,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ,CAAC;aACH,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,SAAS,EAAE,KAAK;4BAChB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;yBACxD,CAAC;qBACH,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe-table.d.ts","sourceRoot":"","sources":["../../src/tools/describe-table.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"describe-table.d.ts","sourceRoot":"","sources":["../../src/tools/describe-table.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+D7D"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { describeTable, isConnected } from '../lib/connection.js';
|
|
3
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
3
4
|
export function registerDescribeTable(server) {
|
|
4
5
|
server.tool('describe_table', 'Get detailed schema for a table: columns, types, indexes, foreign keys, and CREATE statement.', {
|
|
5
6
|
table: z.string().describe('Name of the table to describe'),
|
|
6
7
|
}, async ({ table }) => {
|
|
8
|
+
recordToolCall('describe_table').catch(() => { });
|
|
7
9
|
try {
|
|
8
10
|
if (!isConnected()) {
|
|
9
11
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe-table.js","sourceRoot":"","sources":["../../src/tools/describe-table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"describe-table.js","sourceRoot":"","sources":["../../src/tools/describe-table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,+FAA+F,EAC/F;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;KAC5D,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QAClB,cAAc,CAAC,gBAAgB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACjD,IAAI,CAAC;YACH,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACnB,OAAO;oBACL,OAAO,EAAE,CAAC;4BACR,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gCACnB,KAAK,EAAE,oDAAoD;6BAC5D,CAAC;yBACH,CAAC;oBACF,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;YAEpC,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,IAAI,EAAE,MAAM,CAAC,IAAI;4BACjB,SAAS,EAAE,MAAM,CAAC,QAAQ;4BAC1B,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gCAChC,IAAI,EAAE,CAAC,CAAC,IAAI;gCACZ,IAAI,EAAE,CAAC,CAAC,IAAI;gCACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;gCACpB,aAAa,EAAE,CAAC,CAAC,YAAY;gCAC7B,WAAW,EAAE,CAAC,CAAC,UAAU;6BAC1B,CAAC,CAAC;4BACH,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gCAChC,IAAI,EAAE,CAAC,CAAC,IAAI;gCACZ,OAAO,EAAE,CAAC,CAAC,OAAO;gCAClB,MAAM,EAAE,CAAC,CAAC,MAAM;6BACjB,CAAC,CAAC;4BACH,YAAY,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gCAC1C,MAAM,EAAE,EAAE,CAAC,MAAM;gCACjB,UAAU,EAAE,GAAG,EAAE,CAAC,eAAe,IAAI,EAAE,CAAC,gBAAgB,GAAG;6BAC5D,CAAC,CAAC;4BACH,UAAU,EAAE,MAAM,CAAC,SAAS;yBAC7B,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ,CAAC;aACH,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;yBACxD,CAAC;qBACH,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export-data.d.ts","sourceRoot":"","sources":["../../src/tools/export-data.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"export-data.d.ts","sourceRoot":"","sources":["../../src/tools/export-data.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAuBzE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0D1D"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { executeReadOnlyQuery, isConnected } from '../lib/connection.js';
|
|
3
3
|
import { requirePro } from '../lib/license.js';
|
|
4
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
4
5
|
function toCsv(rows, columns) {
|
|
5
6
|
if (rows.length === 0)
|
|
6
7
|
return '';
|
|
@@ -19,6 +20,7 @@ export function registerExportData(server) {
|
|
|
19
20
|
sql: z.string().describe('SELECT query to export'),
|
|
20
21
|
format: z.enum(['csv', 'json']).describe('Export format: csv or json'),
|
|
21
22
|
}, async ({ sql, format }) => {
|
|
23
|
+
recordToolCall('export_data').catch(() => { });
|
|
22
24
|
try {
|
|
23
25
|
await requirePro();
|
|
24
26
|
if (!isConnected()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export-data.js","sourceRoot":"","sources":["../../src/tools/export-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"export-data.js","sourceRoot":"","sources":["../../src/tools/export-data.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-migration.d.ts","sourceRoot":"","sources":["../../src/tools/generate-migration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"generate-migration.d.ts","sourceRoot":"","sources":["../../src/tools/generate-migration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsCjE"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { requirePro } from '../lib/license.js';
|
|
3
3
|
import { generateMigrationSql } from '../lib/ai-query.js';
|
|
4
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
4
5
|
export function registerGenerateMigration(server) {
|
|
5
6
|
server.tool('generate_migration', 'Generate SQL migration (up + down) from a natural language description. Requires Pro license and AI API key.', {
|
|
6
7
|
description: z.string().describe('Description of the database change (e.g. "add email column to users table")'),
|
|
7
8
|
dialect: z.enum(['sqlite', 'postgresql', 'mysql']).optional().describe('SQL dialect (default: sqlite)'),
|
|
8
9
|
}, async ({ description, dialect }) => {
|
|
10
|
+
recordToolCall('generate_migration').catch(() => { });
|
|
9
11
|
try {
|
|
10
12
|
await requirePro();
|
|
11
13
|
const result = await generateMigrationSql(description, dialect ?? 'sqlite');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-migration.js","sourceRoot":"","sources":["../../src/tools/generate-migration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"generate-migration.js","sourceRoot":"","sources":["../../src/tools/generate-migration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,UAAU,yBAAyB,CAAC,MAAiB;IACzD,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,8GAA8G,EAC9G;QACE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6EAA6E,CAAC;QAC/G,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;KACxG,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE;QACjC,cAAc,CAAC,oBAAoB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC;YACH,MAAM,UAAU,EAAE,CAAC;YAEnB,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,OAAO,IAAI,QAAQ,CAAC,CAAC;YAE5E,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,MAAM,EAAE,MAAM,CAAC,KAAK;4BACpB,QAAQ,EAAE,MAAM,CAAC,OAAO;4BACxB,OAAO,EAAE,OAAO,IAAI,QAAQ;yBAC7B,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ,CAAC;aACH,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;yBACxD,CAAC;qBACH,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-tables.d.ts","sourceRoot":"","sources":["../../src/tools/list-tables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"list-tables.d.ts","sourceRoot":"","sources":["../../src/tools/list-tables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiD1D"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { listTables, isConnected } from '../lib/connection.js';
|
|
2
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
2
3
|
export function registerListTables(server) {
|
|
3
4
|
server.tool('list_tables', 'List all tables in the connected database with row counts and column info.', {}, async () => {
|
|
5
|
+
recordToolCall('list_tables').catch(() => { });
|
|
4
6
|
try {
|
|
5
7
|
if (!isConnected()) {
|
|
6
8
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-tables.js","sourceRoot":"","sources":["../../src/tools/list-tables.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"list-tables.js","sourceRoot":"","sources":["../../src/tools/list-tables.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,IAAI,CACT,aAAa,EACb,4EAA4E,EAC5E,EAAE,EACF,KAAK,IAAI,EAAE;QACT,cAAc,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC;YACH,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACnB,OAAO;oBACL,OAAO,EAAE,CAAC;4BACR,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gCACnB,KAAK,EAAE,oDAAoD;6BAC5D,CAAC;yBACH,CAAC;oBACF,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;YAE5B,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;4BACpC,IAAI,EAAE,CAAC,CAAC,IAAI;4BACZ,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gCAC3B,IAAI,EAAE,CAAC,CAAC,IAAI;gCACZ,IAAI,EAAE,CAAC,CAAC,IAAI;gCACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;6BACrB,CAAC,CAAC;4BACH,SAAS,EAAE,CAAC,CAAC,QAAQ;yBACtB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;qBACd,CAAC;aACH,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;yBACxD,CAAC;qBACH,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"natural-language-query.d.ts","sourceRoot":"","sources":["../../src/tools/natural-language-query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"natural-language-query.d.ts","sourceRoot":"","sources":["../../src/tools/natural-language-query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuDpE"}
|
|
@@ -2,11 +2,13 @@ import { z } from 'zod';
|
|
|
2
2
|
import { isConnected } from '../lib/connection.js';
|
|
3
3
|
import { requirePro } from '../lib/license.js';
|
|
4
4
|
import { naturalLanguageToSql } from '../lib/ai-query.js';
|
|
5
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
5
6
|
export function registerNaturalLanguageQuery(server) {
|
|
6
7
|
server.tool('natural_language_query', 'Convert a natural language question to SQL and execute it. Requires Pro license and ANTHROPIC_API_KEY or OPENAI_API_KEY.', {
|
|
7
8
|
question: z.string().describe('Natural language question about your data'),
|
|
8
9
|
tables: z.array(z.string()).optional().describe('Limit query generation to these tables'),
|
|
9
10
|
}, async ({ question, tables }) => {
|
|
11
|
+
recordToolCall('natural_language_query').catch(() => { });
|
|
10
12
|
try {
|
|
11
13
|
await requirePro();
|
|
12
14
|
if (!isConnected()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"natural-language-query.js","sourceRoot":"","sources":["../../src/tools/natural-language-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"natural-language-query.js","sourceRoot":"","sources":["../../src/tools/natural-language-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,UAAU,4BAA4B,CAAC,MAAiB;IAC5D,MAAM,CAAC,IAAI,CACT,wBAAwB,EACxB,0HAA0H,EAC1H;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;QAC1E,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;KAC1F,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE;QAC7B,cAAc,CAAC,wBAAwB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC;YACH,MAAM,UAAU,EAAE,CAAC;YAEnB,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACnB,OAAO;oBACL,OAAO,EAAE,CAAC;4BACR,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gCACnB,KAAK,EAAE,oDAAoD;6BAC5D,CAAC;yBACH,CAAC;oBACF,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAE5D,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,GAAG,EAAE,MAAM,CAAC,GAAG;4BACf,WAAW,EAAE,MAAM,CAAC,WAAW;4BAC/B,OAAO,EAAE;gCACP,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI;gCACzB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO;gCAC/B,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ;gCAClC,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe;6BAClD;yBACF,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ,CAAC;aACH,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;yBACxD,CAAC;qBACH,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimize-query.d.ts","sourceRoot":"","sources":["../../src/tools/optimize-query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"optimize-query.d.ts","sourceRoot":"","sources":["../../src/tools/optimize-query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAqD7D"}
|
|
@@ -2,10 +2,12 @@ import { z } from 'zod';
|
|
|
2
2
|
import { isConnected } from '../lib/connection.js';
|
|
3
3
|
import { requirePro } from '../lib/license.js';
|
|
4
4
|
import { optimizeQuery } from '../lib/query-optimizer.js';
|
|
5
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
5
6
|
export function registerOptimizeQuery(server) {
|
|
6
7
|
server.tool('optimize_query', 'Analyze a SQL query for performance issues. Shows EXPLAIN plan, suggests indexes, and estimates improvement. Requires Pro license.', {
|
|
7
8
|
sql: z.string().describe('SQL query to analyze'),
|
|
8
9
|
}, async ({ sql }) => {
|
|
10
|
+
recordToolCall('optimize_query').catch(() => { });
|
|
9
11
|
try {
|
|
10
12
|
await requirePro();
|
|
11
13
|
if (!isConnected()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimize-query.js","sourceRoot":"","sources":["../../src/tools/optimize-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"optimize-query.js","sourceRoot":"","sources":["../../src/tools/optimize-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,oIAAoI,EACpI;QACE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;KACjD,EACD,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;QAChB,cAAc,CAAC,gBAAgB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,UAAU,EAAE,CAAC;YAEnB,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACnB,OAAO;oBACL,OAAO,EAAE,CAAC;4BACR,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gCACnB,KAAK,EAAE,oDAAoD;6BAC5D,CAAC;yBACH,CAAC;oBACF,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;YAElC,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,YAAY,EAAE,MAAM,CAAC,WAAW;4BAChC,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gCACxC,IAAI,EAAE,CAAC,CAAC,IAAI;gCACZ,WAAW,EAAE,CAAC,CAAC,WAAW;gCAC1B,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;6BAC3C,CAAC,CAAC;4BACH,qBAAqB,EAAE,MAAM,CAAC,oBAAoB;yBACnD,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ,CAAC;aACH,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;yBACxD,CAAC;qBACH,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoFrD"}
|
package/dist/tools/query.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { executeReadOnlyQuery, executeQuery, isConnected, isWriteQuery } from '../lib/connection.js';
|
|
3
3
|
import { getLicenseStatus } from '../lib/license.js';
|
|
4
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
4
5
|
export function registerQuery(server) {
|
|
5
6
|
server.tool('query', 'Execute a SQL query. Free tier: SELECT only. Pro tier: full read/write with confirmation flag.', {
|
|
6
7
|
sql: z.string().describe('SQL query to execute'),
|
|
7
8
|
params: z.array(z.unknown()).optional().describe('Query parameters for prepared statement'),
|
|
8
9
|
confirm_write: z.boolean().optional().describe('Set to true to confirm write operations (Pro tier only)'),
|
|
9
10
|
}, async ({ sql, params, confirm_write }) => {
|
|
11
|
+
recordToolCall('query').catch(() => { });
|
|
10
12
|
try {
|
|
11
13
|
if (!isConnected()) {
|
|
12
14
|
return {
|
package/dist/tools/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACrG,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"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"}
|
package/mcpize.yaml
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# MCPize manifest - https://mcpize.com
|
|
2
|
+
# Generated by mcpize analyze
|
|
3
|
+
version: 1
|
|
4
|
+
runtime: typescript
|
|
5
|
+
build:
|
|
6
|
+
install: npm install
|
|
7
|
+
command: npm run build
|
|
8
|
+
startCommand:
|
|
9
|
+
type: stdio
|
|
10
|
+
command: node dist/index.js
|
|
11
|
+
credentials:
|
|
12
|
+
- name: TRUSS_LICENSE_KEY
|
|
13
|
+
required: false
|
|
14
|
+
description: License key for Pro features (optional)
|
|
15
|
+
mapping:
|
|
16
|
+
env: TRUSS_LICENSE_KEY
|
|
17
|
+
- name: DATABASE_URL
|
|
18
|
+
required: false
|
|
19
|
+
description: 'Database connection URL (postgres:// or mysql://)'
|
|
20
|
+
mapping:
|
|
21
|
+
env: DATABASE_URL
|
|
22
|
+
- name: ANTHROPIC_API_KEY
|
|
23
|
+
required: false
|
|
24
|
+
description: API key for AI-powered query features (Pro tier)
|
|
25
|
+
mapping:
|
|
26
|
+
env: ANTHROPIC_API_KEY
|
|
27
|
+
- name: OPENAI_API_KEY
|
|
28
|
+
required: false
|
|
29
|
+
description: Alternative AI API key (Pro tier)
|
|
30
|
+
mapping:
|
|
31
|
+
env: OPENAI_API_KEY
|
|
32
|
+
credentials_mode: per_user
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "truss-db-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Database query MCP server for Claude Code — SQLite, PostgreSQL, and MySQL with AI-powered query tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
},
|
|
15
15
|
"keywords": [
|
|
16
16
|
"mcp",
|
|
17
|
+
"mcp-server",
|
|
18
|
+
"model-context-protocol",
|
|
17
19
|
"database",
|
|
18
20
|
"sqlite",
|
|
19
21
|
"postgresql",
|
|
@@ -22,26 +24,38 @@
|
|
|
22
24
|
"query",
|
|
23
25
|
"claude",
|
|
24
26
|
"claude-code",
|
|
25
|
-
"
|
|
27
|
+
"cursor",
|
|
28
|
+
"ai",
|
|
29
|
+
"ai-agent",
|
|
30
|
+
"agent",
|
|
31
|
+
"db",
|
|
32
|
+
"orm",
|
|
33
|
+
"tool"
|
|
26
34
|
],
|
|
27
35
|
"author": "TRUSS",
|
|
28
36
|
"license": "MIT",
|
|
29
37
|
"dependencies": {
|
|
30
38
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
31
|
-
"better-sqlite3": "^11.0.0"
|
|
39
|
+
"better-sqlite3": "^11.0.0",
|
|
40
|
+
"stripe": "^21.0.1"
|
|
32
41
|
},
|
|
33
42
|
"peerDependencies": {
|
|
34
43
|
"pg": "^8.12.0",
|
|
35
44
|
"mysql2": "^3.11.0"
|
|
36
45
|
},
|
|
37
46
|
"peerDependenciesMeta": {
|
|
38
|
-
"pg": {
|
|
39
|
-
|
|
47
|
+
"pg": {
|
|
48
|
+
"optional": true
|
|
49
|
+
},
|
|
50
|
+
"mysql2": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
40
53
|
},
|
|
41
54
|
"devDependencies": {
|
|
42
55
|
"typescript": "^5.5.0",
|
|
43
56
|
"tsx": "^4.19.0",
|
|
44
57
|
"@types/better-sqlite3": "^7.6.0",
|
|
45
58
|
"@types/node": "^22.0.0"
|
|
46
|
-
}
|
|
59
|
+
},
|
|
60
|
+
"mcpName": "io.github.claw-factory/truss-db-mcp"
|
|
47
61
|
}
|
package/server.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.claw-factory/truss-db-mcp",
|
|
4
|
+
"title": "TRUSS DB MCP — Database Query Server",
|
|
5
|
+
"description": "Database query MCP server with natural language SQL",
|
|
6
|
+
"version": "1.0.1",
|
|
7
|
+
"packages": [
|
|
8
|
+
{
|
|
9
|
+
"registryType": "npm",
|
|
10
|
+
"identifier": "truss-db-mcp",
|
|
11
|
+
"version": "1.0.1",
|
|
12
|
+
"runtimeHint": "node",
|
|
13
|
+
"transport": {
|
|
14
|
+
"type": "stdio"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"sourceUrl": "https://github.com/claw-factory/truss-db-mcp",
|
|
19
|
+
"license": "MIT"
|
|
20
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import Stripe from 'stripe';
|
|
2
|
+
|
|
3
|
+
const stripeKey = process.env.STRIPE_SECRET_KEY;
|
|
4
|
+
const customerId = process.env.STRIPE_CUSTOMER_ID;
|
|
5
|
+
|
|
6
|
+
let stripe: Stripe | null = null;
|
|
7
|
+
|
|
8
|
+
if (stripeKey) {
|
|
9
|
+
stripe = new Stripe(stripeKey);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Record a tool call for usage-based billing via Stripe Billing Meters.
|
|
14
|
+
* Non-blocking — failures are logged but do not interrupt the tool call.
|
|
15
|
+
* Requires STRIPE_SECRET_KEY and STRIPE_CUSTOMER_ID env vars.
|
|
16
|
+
*/
|
|
17
|
+
export async function recordToolCall(toolName: string): Promise<void> {
|
|
18
|
+
if (!stripe || !customerId) return;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
await stripe.billing.meterEvents.create({
|
|
22
|
+
event_name: 'mcp_tool_call',
|
|
23
|
+
payload: {
|
|
24
|
+
stripe_customer_id: customerId,
|
|
25
|
+
value: '1',
|
|
26
|
+
},
|
|
27
|
+
identifier: `${customerId}_${toolName}_${Date.now()}`,
|
|
28
|
+
});
|
|
29
|
+
} catch (err) {
|
|
30
|
+
// Non-blocking — log and continue
|
|
31
|
+
console.error(`[billing] meter event failed for ${toolName}:`, (err as Error).message);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
package/src/tools/connect.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { connectSqlite } from '../lib/connection.js';
|
|
4
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
4
5
|
|
|
5
6
|
export function registerConnect(server: McpServer): void {
|
|
6
7
|
server.tool(
|
|
@@ -10,6 +11,7 @@ export function registerConnect(server: McpServer): void {
|
|
|
10
11
|
path: z.string().describe('Path to the SQLite database file'),
|
|
11
12
|
},
|
|
12
13
|
async ({ path }) => {
|
|
14
|
+
recordToolCall('connect').catch(() => {});
|
|
13
15
|
try {
|
|
14
16
|
const info = connectSqlite(path);
|
|
15
17
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { describeTable, isConnected } from '../lib/connection.js';
|
|
4
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
4
5
|
|
|
5
6
|
export function registerDescribeTable(server: McpServer): void {
|
|
6
7
|
server.tool(
|
|
@@ -10,6 +11,7 @@ export function registerDescribeTable(server: McpServer): void {
|
|
|
10
11
|
table: z.string().describe('Name of the table to describe'),
|
|
11
12
|
},
|
|
12
13
|
async ({ table }) => {
|
|
14
|
+
recordToolCall('describe_table').catch(() => {});
|
|
13
15
|
try {
|
|
14
16
|
if (!isConnected()) {
|
|
15
17
|
return {
|
package/src/tools/export-data.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { executeReadOnlyQuery, isConnected } from '../lib/connection.js';
|
|
4
4
|
import { requirePro } from '../lib/license.js';
|
|
5
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
5
6
|
|
|
6
7
|
function toCsv(rows: Record<string, unknown>[], columns: string[]): string {
|
|
7
8
|
if (rows.length === 0) return '';
|
|
@@ -30,6 +31,7 @@ export function registerExportData(server: McpServer): void {
|
|
|
30
31
|
format: z.enum(['csv', 'json']).describe('Export format: csv or json'),
|
|
31
32
|
},
|
|
32
33
|
async ({ sql, format }) => {
|
|
34
|
+
recordToolCall('export_data').catch(() => {});
|
|
33
35
|
try {
|
|
34
36
|
await requirePro();
|
|
35
37
|
|
|
@@ -2,6 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { requirePro } from '../lib/license.js';
|
|
4
4
|
import { generateMigrationSql } from '../lib/ai-query.js';
|
|
5
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
5
6
|
|
|
6
7
|
export function registerGenerateMigration(server: McpServer): void {
|
|
7
8
|
server.tool(
|
|
@@ -12,6 +13,7 @@ export function registerGenerateMigration(server: McpServer): void {
|
|
|
12
13
|
dialect: z.enum(['sqlite', 'postgresql', 'mysql']).optional().describe('SQL dialect (default: sqlite)'),
|
|
13
14
|
},
|
|
14
15
|
async ({ description, dialect }) => {
|
|
16
|
+
recordToolCall('generate_migration').catch(() => {});
|
|
15
17
|
try {
|
|
16
18
|
await requirePro();
|
|
17
19
|
|
package/src/tools/list-tables.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { listTables, isConnected } from '../lib/connection.js';
|
|
3
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
3
4
|
|
|
4
5
|
export function registerListTables(server: McpServer): void {
|
|
5
6
|
server.tool(
|
|
@@ -7,6 +8,7 @@ export function registerListTables(server: McpServer): void {
|
|
|
7
8
|
'List all tables in the connected database with row counts and column info.',
|
|
8
9
|
{},
|
|
9
10
|
async () => {
|
|
11
|
+
recordToolCall('list_tables').catch(() => {});
|
|
10
12
|
try {
|
|
11
13
|
if (!isConnected()) {
|
|
12
14
|
return {
|
|
@@ -3,6 +3,7 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
3
3
|
import { isConnected } from '../lib/connection.js';
|
|
4
4
|
import { requirePro } from '../lib/license.js';
|
|
5
5
|
import { naturalLanguageToSql } from '../lib/ai-query.js';
|
|
6
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
6
7
|
|
|
7
8
|
export function registerNaturalLanguageQuery(server: McpServer): void {
|
|
8
9
|
server.tool(
|
|
@@ -13,6 +14,7 @@ export function registerNaturalLanguageQuery(server: McpServer): void {
|
|
|
13
14
|
tables: z.array(z.string()).optional().describe('Limit query generation to these tables'),
|
|
14
15
|
},
|
|
15
16
|
async ({ question, tables }) => {
|
|
17
|
+
recordToolCall('natural_language_query').catch(() => {});
|
|
16
18
|
try {
|
|
17
19
|
await requirePro();
|
|
18
20
|
|
|
@@ -3,6 +3,7 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
3
3
|
import { isConnected } from '../lib/connection.js';
|
|
4
4
|
import { requirePro } from '../lib/license.js';
|
|
5
5
|
import { optimizeQuery } from '../lib/query-optimizer.js';
|
|
6
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
6
7
|
|
|
7
8
|
export function registerOptimizeQuery(server: McpServer): void {
|
|
8
9
|
server.tool(
|
|
@@ -12,6 +13,7 @@ export function registerOptimizeQuery(server: McpServer): void {
|
|
|
12
13
|
sql: z.string().describe('SQL query to analyze'),
|
|
13
14
|
},
|
|
14
15
|
async ({ sql }) => {
|
|
16
|
+
recordToolCall('optimize_query').catch(() => {});
|
|
15
17
|
try {
|
|
16
18
|
await requirePro();
|
|
17
19
|
|
package/src/tools/query.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { executeReadOnlyQuery, executeQuery, isConnected, isWriteQuery } from '../lib/connection.js';
|
|
4
4
|
import { getLicenseStatus } from '../lib/license.js';
|
|
5
|
+
import { recordToolCall } from '../lib/billing.js';
|
|
5
6
|
|
|
6
7
|
export function registerQuery(server: McpServer): void {
|
|
7
8
|
server.tool(
|
|
@@ -13,6 +14,7 @@ export function registerQuery(server: McpServer): void {
|
|
|
13
14
|
confirm_write: z.boolean().optional().describe('Set to true to confirm write operations (Pro tier only)'),
|
|
14
15
|
},
|
|
15
16
|
async ({ sql, params, confirm_write }) => {
|
|
17
|
+
recordToolCall('query').catch(() => {});
|
|
16
18
|
try {
|
|
17
19
|
if (!isConnected()) {
|
|
18
20
|
return {
|
package/evals/test.db
DELETED
|
Binary file
|