@mcptoolgate/client 1.0.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/README.md ADDED
@@ -0,0 +1,106 @@
1
+ # MCP Tool Gate Client
2
+
3
+ Lightweight MCP client for integrating MCP Tool Gate with Claude Desktop and other MCP clients.
4
+
5
+ ## Installation
6
+
7
+ ### Quick Start (npx)
8
+
9
+ ```json
10
+ {
11
+ "mcpServers": {
12
+ "mcptoolgate": {
13
+ "command": "npx",
14
+ "args": ["-y", "@mcptoolgate/client"],
15
+ "env": {
16
+ "MCPTOOLGATE_API_KEY": "your-api-key-here"
17
+ }
18
+ }
19
+ }
20
+ }
21
+ ```
22
+
23
+ ### Local Development
24
+
25
+ ```bash
26
+ # Install dependencies
27
+ npm install
28
+
29
+ # Build the client
30
+ npm run build
31
+
32
+ # Link for local testing
33
+ npm link
34
+ ```
35
+
36
+ ## Configuration
37
+
38
+ The client requires two environment variables:
39
+
40
+ - **MCPTOOLGATE_API_KEY** (required): Your API key from the MCP Tool Gate dashboard
41
+ - **MCPTOOLGATE_URL** (optional): Backend URL (defaults to production)
42
+
43
+ ## Usage with Claude Desktop
44
+
45
+ 1. **Generate API Key:**
46
+ - Log in to your MCP Tool Gate dashboard
47
+ - Go to Settings → API Keys
48
+ - Click "Generate New Key"
49
+ - Copy the key (shown only once!)
50
+
51
+ 2. **Configure Claude Desktop:**
52
+
53
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
54
+
55
+ ```json
56
+ {
57
+ "mcpServers": {
58
+ "mcptoolgate": {
59
+ "command": "npx",
60
+ "args": ["-y", "@mcptoolgate/client"],
61
+ "env": {
62
+ "MCPTOOLGATE_API_KEY": "mgk_your_key_here"
63
+ }
64
+ }
65
+ }
66
+ }
67
+ ```
68
+
69
+ 3. **Restart Claude Desktop**
70
+
71
+ 4. **Start using your tools!**
72
+ - Your configured tools will appear automatically
73
+ - Destructive actions will require approval
74
+ - Check your dashboard for approval requests
75
+
76
+ ## Features
77
+
78
+ - ✅ **Zero Configuration**: Just add your API key
79
+ - ✅ **Automatic Tool Discovery**: Tools from your dashboard appear instantly
80
+ - ✅ **Policy Enforcement**: Backend applies all your configured policies
81
+ - ✅ **Approval Workflows**: Destructive actions pause for human review
82
+ - ✅ **Real-time**: No caching, always up-to-date
83
+
84
+ ## Troubleshooting
85
+
86
+ ### Tools not appearing?
87
+
88
+ 1. Check your API key is correct
89
+ 2. Verify the key isn't revoked in the dashboard
90
+ 3. Check Claude Desktop logs: `tail -f ~/Library/Logs/Claude/mcp*.log`
91
+
92
+ ### Execution failing?
93
+
94
+ 1. Check tool adapter configuration in dashboard
95
+ 2. Verify credentials (Slack webhooks, GitHub tokens, etc.)
96
+ 3. Check audit logs in dashboard for error details
97
+
98
+ ## Support
99
+
100
+ - Dashboard: https://your-dashboard-url.com
101
+ - Documentation: https://docs.mcptoolgate.com
102
+ - Issues: https://github.com/your-org/mcp-tool-gate/issues
103
+
104
+ ## License
105
+
106
+ MIT
package/dist/api.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ export interface Tool {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: any;
5
+ }
6
+ export interface ExecutionResult {
7
+ status: 'completed' | 'pending_approval' | 'denied' | 'failed';
8
+ result?: any;
9
+ approval_request_id?: string;
10
+ message?: string;
11
+ error?: string;
12
+ }
13
+ export declare class MCPToolGateAPI {
14
+ private client;
15
+ constructor(apiKey: string, baseURL: string);
16
+ /**
17
+ * List all available tools for the authenticated tenant
18
+ */
19
+ listTools(): Promise<Tool[]>;
20
+ /**
21
+ * Execute a tool with given input
22
+ */
23
+ executeTool(toolName: string, input: any): Promise<ExecutionResult>;
24
+ /**
25
+ * Check approval status for a pending request
26
+ */
27
+ checkApprovalStatus(requestId: string): Promise<any>;
28
+ }
29
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,IAAI;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,WAAW,GAAG,kBAAkB,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC/D,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAW3C;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAUlC;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,eAAe,CAAC;IAmBzE;;OAEG;IACG,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;CAS7D"}
package/dist/api.js ADDED
@@ -0,0 +1,61 @@
1
+ import axios from 'axios';
2
+ export class MCPToolGateAPI {
3
+ client;
4
+ constructor(apiKey, baseURL) {
5
+ this.client = axios.create({
6
+ baseURL,
7
+ headers: {
8
+ 'x-api-key': apiKey,
9
+ 'Content-Type': 'application/json',
10
+ },
11
+ timeout: 30000, // 30 second timeout
12
+ });
13
+ }
14
+ /**
15
+ * List all available tools for the authenticated tenant
16
+ */
17
+ async listTools() {
18
+ try {
19
+ const response = await this.client.get('/v1/mcp/tools');
20
+ return response.data.tools || [];
21
+ }
22
+ catch (error) {
23
+ console.error('[MCP Tool Gate API] Error listing tools:', error.message);
24
+ throw new Error(`Failed to list tools: ${error.response?.data?.error || error.message}`);
25
+ }
26
+ }
27
+ /**
28
+ * Execute a tool with given input
29
+ */
30
+ async executeTool(toolName, input) {
31
+ try {
32
+ const response = await this.client.post('/v1/mcp/execute', {
33
+ tool: toolName,
34
+ input,
35
+ });
36
+ return response.data;
37
+ }
38
+ catch (error) {
39
+ console.error('[MCP Tool Gate API] Error executing tool:', error.message);
40
+ // Return failed status instead of throwing
41
+ return {
42
+ status: 'failed',
43
+ error: error.response?.data?.error || error.message,
44
+ };
45
+ }
46
+ }
47
+ /**
48
+ * Check approval status for a pending request
49
+ */
50
+ async checkApprovalStatus(requestId) {
51
+ try {
52
+ const response = await this.client.get(`/v1/mcp/approvals/${requestId}`);
53
+ return response.data;
54
+ }
55
+ catch (error) {
56
+ console.error('[MCP Tool Gate API] Error checking approval:', error.message);
57
+ throw new Error(`Failed to check approval: ${error.response?.data?.error || error.message}`);
58
+ }
59
+ }
60
+ }
61
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAwB,MAAM,OAAO,CAAC;AAgB7C,MAAM,OAAO,cAAc;IACf,MAAM,CAAgB;IAE9B,YAAY,MAAc,EAAE,OAAe;QACvC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YACvB,OAAO;YACP,OAAO,EAAE;gBACL,WAAW,EAAE,MAAM;gBACnB,cAAc,EAAE,kBAAkB;aACrC;YACD,OAAO,EAAE,KAAK,EAAE,oBAAoB;SACvC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS;QACX,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YACxD,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QACrC,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YACzE,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7F,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,QAAgB,EAAE,KAAU;QAC1C,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE;gBACvD,IAAI,EAAE,QAAQ;gBACd,KAAK;aACR,CAAC,CAAC;YAEH,OAAO,QAAQ,CAAC,IAAI,CAAC;QACzB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,2CAA2C,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAE1E,2CAA2C;YAC3C,OAAO;gBACH,MAAM,EAAE,QAAQ;gBAChB,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC,OAAO;aACtD,CAAC;QACN,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,mBAAmB,CAAC,SAAiB;QACvC,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAC;YACzE,OAAO,QAAQ,CAAC,IAAI,CAAC;QACzB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,8CAA8C,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7E,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACjG,CAAC;IACL,CAAC;CACJ"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
+ import { MCPToolGateAPI } from './api.js';
6
+ // Get configuration from environment
7
+ const API_KEY = process.env.MCPTOOLGATE_API_KEY;
8
+ const API_URL = process.env.MCPTOOLGATE_URL || 'https://app.mcptoolgate.com';
9
+ if (!API_KEY) {
10
+ console.error('Error: MCPTOOLGATE_API_KEY environment variable is required');
11
+ process.exit(1);
12
+ }
13
+ // Initialize API client
14
+ const api = new MCPToolGateAPI(API_KEY, API_URL);
15
+ // Create MCP server
16
+ const server = new Server({
17
+ name: 'mcptoolgate',
18
+ version: '1.0.0',
19
+ }, {
20
+ capabilities: {
21
+ tools: {},
22
+ },
23
+ });
24
+ // Handle tool listing
25
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
26
+ try {
27
+ const tools = await api.listTools();
28
+ return {
29
+ tools: tools.map((tool) => ({
30
+ name: tool.name,
31
+ description: tool.description,
32
+ inputSchema: tool.inputSchema,
33
+ })),
34
+ };
35
+ }
36
+ catch (error) {
37
+ console.error('Error listing tools:', error);
38
+ throw error;
39
+ }
40
+ });
41
+ // Handle tool execution
42
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
43
+ try {
44
+ const { name, arguments: args } = request.params;
45
+ console.error(`[MCP Tool Gate] Executing tool: ${name}`);
46
+ const result = await api.executeTool(name, args || {});
47
+ // Handle different execution statuses
48
+ if (result.status === 'pending_approval') {
49
+ return {
50
+ content: [
51
+ {
52
+ type: 'text',
53
+ text: `⏸️ Tool execution paused - approval required.\n\nApproval Request ID: ${result.approval_request_id}\n\nPlease check your MCP Tool Gate dashboard to approve or deny this request.`,
54
+ },
55
+ ],
56
+ };
57
+ }
58
+ if (result.status === 'denied') {
59
+ return {
60
+ content: [
61
+ {
62
+ type: 'text',
63
+ text: `❌ Tool execution denied by policy.\n\n${result.message || 'This action is not allowed.'}`,
64
+ },
65
+ ],
66
+ };
67
+ }
68
+ if (result.status === 'failed') {
69
+ return {
70
+ content: [
71
+ {
72
+ type: 'text',
73
+ text: `❌ Tool execution failed.\n\n${result.error || 'An error occurred during execution.'}`,
74
+ },
75
+ ],
76
+ isError: true,
77
+ };
78
+ }
79
+ // Success
80
+ return {
81
+ content: [
82
+ {
83
+ type: 'text',
84
+ text: typeof result.result === 'string'
85
+ ? result.result
86
+ : JSON.stringify(result.result, null, 2),
87
+ },
88
+ ],
89
+ };
90
+ }
91
+ catch (error) {
92
+ console.error('[MCP Tool Gate] Tool execution error:', error);
93
+ return {
94
+ content: [
95
+ {
96
+ type: 'text',
97
+ text: `Error: ${error.message || 'Tool execution failed'}`,
98
+ },
99
+ ],
100
+ isError: true,
101
+ };
102
+ }
103
+ });
104
+ // Start server
105
+ async function main() {
106
+ const transport = new StdioServerTransport();
107
+ await server.connect(transport);
108
+ console.error('[MCP Tool Gate] Client connected to', API_URL);
109
+ }
110
+ main().catch((error) => {
111
+ console.error('[MCP Tool Gate] Fatal error:', error);
112
+ process.exit(1);
113
+ });
114
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@mcptoolgate/client",
3
+ "version": "1.0.0",
4
+ "description": "MCP Tool Gate client for Claude Desktop - secure MCP tool governance",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "mcptoolgate-client": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "keywords": [
16
+ "mcp",
17
+ "claude",
18
+ "security",
19
+ "governance",
20
+ "approval"
21
+ ],
22
+ "author": "MCP Tool Gate",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "@modelcontextprotocol/sdk": "^0.5.0",
26
+ "axios": "^1.6.0"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^20.0.0",
30
+ "typescript": "^5.3.0"
31
+ },
32
+ "engines": {
33
+ "node": ">=18.0.0"
34
+ }
35
+ }
package/src/api.ts ADDED
@@ -0,0 +1,78 @@
1
+ import axios, { AxiosInstance } from 'axios';
2
+
3
+ export interface Tool {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: any;
7
+ }
8
+
9
+ export interface ExecutionResult {
10
+ status: 'completed' | 'pending_approval' | 'denied' | 'failed';
11
+ result?: any;
12
+ approval_request_id?: string;
13
+ message?: string;
14
+ error?: string;
15
+ }
16
+
17
+ export class MCPToolGateAPI {
18
+ private client: AxiosInstance;
19
+
20
+ constructor(apiKey: string, baseURL: string) {
21
+ this.client = axios.create({
22
+ baseURL,
23
+ headers: {
24
+ 'x-api-key': apiKey,
25
+ 'Content-Type': 'application/json',
26
+ },
27
+ timeout: 30000, // 30 second timeout
28
+ });
29
+ }
30
+
31
+ /**
32
+ * List all available tools for the authenticated tenant
33
+ */
34
+ async listTools(): Promise<Tool[]> {
35
+ try {
36
+ const response = await this.client.get('/v1/mcp/tools');
37
+ return response.data.tools || [];
38
+ } catch (error: any) {
39
+ console.error('[MCP Tool Gate API] Error listing tools:', error.message);
40
+ throw new Error(`Failed to list tools: ${error.response?.data?.error || error.message}`);
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Execute a tool with given input
46
+ */
47
+ async executeTool(toolName: string, input: any): Promise<ExecutionResult> {
48
+ try {
49
+ const response = await this.client.post('/v1/mcp/execute', {
50
+ tool: toolName,
51
+ input,
52
+ });
53
+
54
+ return response.data;
55
+ } catch (error: any) {
56
+ console.error('[MCP Tool Gate API] Error executing tool:', error.message);
57
+
58
+ // Return failed status instead of throwing
59
+ return {
60
+ status: 'failed',
61
+ error: error.response?.data?.error || error.message,
62
+ };
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Check approval status for a pending request
68
+ */
69
+ async checkApprovalStatus(requestId: string): Promise<any> {
70
+ try {
71
+ const response = await this.client.get(`/v1/mcp/approvals/${requestId}`);
72
+ return response.data;
73
+ } catch (error: any) {
74
+ console.error('[MCP Tool Gate API] Error checking approval:', error.message);
75
+ throw new Error(`Failed to check approval: ${error.response?.data?.error || error.message}`);
76
+ }
77
+ }
78
+ }
package/src/index.ts ADDED
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
4
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
+ import {
6
+ CallToolRequestSchema,
7
+ ListToolsRequestSchema,
8
+ } from '@modelcontextprotocol/sdk/types.js';
9
+ import { MCPToolGateAPI } from './api.js';
10
+
11
+ // Get configuration from environment
12
+ const API_KEY = process.env.MCPTOOLGATE_API_KEY;
13
+ const API_URL = process.env.MCPTOOLGATE_URL || 'https://app.mcptoolgate.com';
14
+
15
+ if (!API_KEY) {
16
+ console.error('Error: MCPTOOLGATE_API_KEY environment variable is required');
17
+ process.exit(1);
18
+ }
19
+
20
+ // Initialize API client
21
+ const api = new MCPToolGateAPI(API_KEY, API_URL);
22
+
23
+ // Create MCP server
24
+ const server = new Server(
25
+ {
26
+ name: 'mcptoolgate',
27
+ version: '1.0.0',
28
+ },
29
+ {
30
+ capabilities: {
31
+ tools: {},
32
+ },
33
+ }
34
+ );
35
+
36
+ // Handle tool listing
37
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
38
+ try {
39
+ const tools = await api.listTools();
40
+
41
+ return {
42
+ tools: tools.map((tool: any) => ({
43
+ name: tool.name,
44
+ description: tool.description,
45
+ inputSchema: tool.inputSchema,
46
+ })),
47
+ };
48
+ } catch (error) {
49
+ console.error('Error listing tools:', error);
50
+ throw error;
51
+ }
52
+ });
53
+
54
+ // Handle tool execution
55
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
56
+ try {
57
+ const { name, arguments: args } = request.params;
58
+
59
+ console.error(`[MCP Tool Gate] Executing tool: ${name}`);
60
+
61
+ const result = await api.executeTool(name, args || {});
62
+
63
+ // Handle different execution statuses
64
+ if (result.status === 'pending_approval') {
65
+ return {
66
+ content: [
67
+ {
68
+ type: 'text',
69
+ text: `⏸️ Tool execution paused - approval required.\n\nApproval Request ID: ${result.approval_request_id}\n\nPlease check your MCP Tool Gate dashboard to approve or deny this request.`,
70
+ },
71
+ ],
72
+ };
73
+ }
74
+
75
+ if (result.status === 'denied') {
76
+ return {
77
+ content: [
78
+ {
79
+ type: 'text',
80
+ text: `❌ Tool execution denied by policy.\n\n${result.message || 'This action is not allowed.'}`,
81
+ },
82
+ ],
83
+ };
84
+ }
85
+
86
+ if (result.status === 'failed') {
87
+ return {
88
+ content: [
89
+ {
90
+ type: 'text',
91
+ text: `❌ Tool execution failed.\n\n${result.error || 'An error occurred during execution.'}`,
92
+ },
93
+ ],
94
+ isError: true,
95
+ };
96
+ }
97
+
98
+ // Success
99
+ return {
100
+ content: [
101
+ {
102
+ type: 'text',
103
+ text: typeof result.result === 'string'
104
+ ? result.result
105
+ : JSON.stringify(result.result, null, 2),
106
+ },
107
+ ],
108
+ };
109
+ } catch (error: any) {
110
+ console.error('[MCP Tool Gate] Tool execution error:', error);
111
+
112
+ return {
113
+ content: [
114
+ {
115
+ type: 'text',
116
+ text: `Error: ${error.message || 'Tool execution failed'}`,
117
+ },
118
+ ],
119
+ isError: true,
120
+ };
121
+ }
122
+ });
123
+
124
+ // Start server
125
+ async function main() {
126
+ const transport = new StdioServerTransport();
127
+ await server.connect(transport);
128
+ console.error('[MCP Tool Gate] Client connected to', API_URL);
129
+ }
130
+
131
+ main().catch((error) => {
132
+ console.error('[MCP Tool Gate] Fatal error:', error);
133
+ process.exit(1);
134
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "moduleResolution": "node",
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true
16
+ },
17
+ "include": [
18
+ "src/**/*"
19
+ ],
20
+ "exclude": [
21
+ "node_modules",
22
+ "dist"
23
+ ]
24
+ }