Skip to content

Commit 8fb170d

Browse files
authored
Merge pull request #13 from CheckPointSW/session_and_logs
Session and logs
2 parents 2bbe934 + 0ea1d03 commit 8fb170d

File tree

8 files changed

+138
-115
lines changed

8 files changed

+138
-115
lines changed

README.md

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ The Model Context Protocol (MCP) is a standardized interface that allows AI agen
1010

1111
## Demo
1212

13-
<!-- Place a link or embed for a demo video here -->
13+
[![Watch the demo](https://img.youtube.com/vi/QKBcD_99W3s/0.jpg)](https://www.youtube.com/watch?v=QKBcD_99W3s)
1414

15-
## Use Cases
15+
## Example Use Cases
1616

1717
### Ensure regulatory compliance with industry standards
1818
Prompt: Check if my gateway configuration meets PCI-DSS/HIPAA/GDPR requirements.
@@ -21,10 +21,10 @@ Prompt: Check if my gateway configuration meets PCI-DSS/HIPAA/GDPR requirements.
2121
Prompt: List all firewall rules that allow traffic from any source to any destination on any port. Highlight rules that are disabled or unused.
2222

2323
### Source → Destination Path Analysis
24-
Prompt: Can you check in my policy if a HOST or Network can access the internet?
24+
Prompt: Can you check in my policy if a host or network can access the internet?
2525

2626
### Recommendation for rulebase optimization
27-
Prompt: Take a look at the internet-facing rules in my policy and suggest improvements. Identify if there are any rules that should be strengthened or loosened. Consider both security risks and administrative overhead. In your recommendations, refer only to specific rules that can be changed or suggest adding new ones.
27+
Prompt: Take a look at the internet-facing rules in my policy and suggest improvements. Identify any rules that should be strengthened or loosened. Consider both security risks and administrative overhead. In your recommendations, refer only to specific rules that can be changed or suggest adding new ones.
2828

2929
### Custom policy visualizations
3030
Prompt: Please create a visual report that shows which services are allowed in my network, under which conditions, and which services are strictly blocked.
@@ -42,7 +42,7 @@ Authenticate to Check Point Smart-1 Cloud using an API key.
4242
- **How to generate an API key:**
4343
In your Smart-1 Cloud dashboard, go to **Settings → API & SmartConsole** and generate an API key.
4444
Copy the key and the server login URL (excluding the `/login` suffix) to your client settings.
45-
![alt text](s1c_api_key.png)
45+
![alt text](./resources/s1c_api_key.png)
4646

4747
Set the following environment variables:
4848

@@ -74,8 +74,23 @@ Set the following environment variables:
7474

7575
## Client Configuration
7676

77-
This server can be used with Claude Desktop, Cursor, GitHub Copilot MCP integrations, or any other MCP client.
78-
> Note: Due to the nature of management API calls, using this server may require a paid subscription to the model provider to handle token limits and context windows.
77+
### Prerequisites
78+
79+
Download and install the latest version of [Node.js](https://nodejs.org/en/download/) if you don't already have it installed.
80+
You can check your installed version by running:
81+
82+
```bash
83+
node -v # Should print "v22" or higher
84+
nvm current # Should print "v22" or higher
85+
```
86+
87+
### Supported Clients
88+
89+
This server has been tested with Claude Desktop, Cursor, GitHub Copilot, and Windsurf clients.
90+
It is expected to work with any MCP client that supports the Model Context Protocol.
91+
92+
> **Note:** Due to the nature of management API calls and the variety of server tools, using this server may require a paid subscription to the model provider to support token limits and context window sizes.
93+
> For smaller models, you can reduce token usage by limiting the number of enabled tools in the client.
7994
8095
### Smart-1 Cloud Example
8196

@@ -114,7 +129,7 @@ This server can be used with Claude Desktop, Cursor, GitHub Copilot MCP integrat
114129
}
115130
```
116131

117-
> Set only the environment variables required for your authentication method (see above).
132+
> Set only the environment variables required for your authentication method.
118133
119134
### Configuring the Claude Desktop App
120135

@@ -150,14 +165,56 @@ Add the server configuration:
150165
}
151166
```
152167

168+
### VSCode
169+
170+
Enter VSCode settings and type "mcp" in the search bar.
171+
You should see the option to edit the configuration file.
172+
Add this configuration:
173+
174+
```json
175+
{
176+
...
177+
"mcp": {
178+
"inputs": [],
179+
"servers": {
180+
"quantum-management": {
181+
"command": "npx",
182+
"args": [
183+
"@chkp/quantum_management_mcp"
184+
],
185+
"env": {
186+
"MANAGEMENT_HOST": "YOUR_MANAGEMENT_IP_OR_HOST_NAME",
187+
"MANAGEMENT_PORT": "443", // optional, default is 443
188+
"API_KEY": "YOUR_API_KEY", // or use USERNAME and PASSWORD
189+
"USERNAME": "YOUR_USERNAME", // optional
190+
"PASSWORD": "YOUR_PASSWORD" // optional
191+
}
192+
}
193+
}
194+
},
195+
...
196+
}
197+
```
198+
199+
### Windsurf
200+
201+
Enter Windsurf settings and type "mcp" in the search bar.
202+
You should see the option to edit the configuration file.
203+
Add the configuration as Claude Desktop App.
204+
205+
### Cursor
206+
207+
Enter Cursor settings and click on "MCP Servers" in the left menu.
208+
You should see the option to add a new MCP Server.
209+
Add the configuration as Claude Desktop App.
153210
---
154211

155212
## Development
156213

157214
### Prerequisites
158215

159216
- Node.js 22+
160-
- npm 8+
217+
- npm 10+
161218

162219
### Setup
163220

@@ -175,7 +232,7 @@ npm run build
175232

176233
### Running Locally
177234

178-
Run the server locally for development using [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) or any MCP client.
235+
You can run the server locally for development using [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) or any compatible MCP client.
179236

180237
```bash
181238
node FULL_PATH_TO_SERVER/packages/management/dist/index.js --s1c-url|--management-host --api-key|--username|--password
@@ -187,4 +244,4 @@ node FULL_PATH_TO_SERVER/packages/management/dist/index.js --s1c-url|--managemen
187244

188245
1. **Authentication keys and credentials are never shared with the model.** They are used only by the MCP server to authenticate with your Check Point management system.
189246
2. **Only use client implementations you trust.** Malicious or untrusted clients could misuse your credentials or access data improperly.
190-
3. **Management data is exposed to the model.** Use models and providers that comply with your organization’s policies on sensitive data and PII handling.
247+
3. **Management data is exposed to the model.** Ensure that you only use models and providers that comply with your organization’s policies for handling sensitive data and PII.

packages/infra/src/api-client.ts

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ function getMainPackageUserAgent(): string {
99
return "Check Point MCP API Client/v1.0";
1010
}
1111

12-
// Constants for API URLs
13-
export const ON_PREM_CI_BASE_URL = "{}/{}/api/v2/environments/{}/web_api";
14-
1512
/**
1613
* Response from an API client call
1714
*/
@@ -26,11 +23,20 @@ export class ClientResponse {
2623
* Base class for API clients
2724
*/
2825
export abstract class APIClientBase {
26+
private static _instance: APIClientBase;
2927
protected sid: string | null = null;
28+
protected sessionTimeout: number | null = null; // in seconds
29+
protected sessionStart: number | null = null; // timestamp when session was created
30+
3031

3132
constructor(
3233
protected readonly apiKey: string,
33-
) {}
34+
) {
35+
if (APIClientBase._instance) {
36+
return APIClientBase._instance;
37+
}
38+
APIClientBase._instance = this;
39+
}
3440

3541
/**
3642
* Get the host URL for the API client
@@ -63,10 +69,11 @@ export abstract class APIClientBase {
6369
data: Record<string, any>,
6470
params?: Record<string, any>
6571
): Promise<ClientResponse> {
66-
if (!this.sid) {
67-
this.sid = await this.loginWithApiKey();
72+
73+
if (!this.sid || this.isSessionExpired()) {
74+
this.sid = await this.login();
6875
}
69-
76+
7077
return await APIClientBase.makeRequest(
7178
this.getHost(),
7279
method,
@@ -77,19 +84,30 @@ export abstract class APIClientBase {
7784
);
7885
}
7986

87+
/**
88+
* Check if the session is expired based on sessionTimeout and sessionStart
89+
*/
90+
protected isSessionExpired(): boolean {
91+
if (!this.sid || !this.sessionTimeout || !this.sessionStart) return true;
92+
const now = Date.now();
93+
// Add a small buffer (5 seconds) to avoid edge cases
94+
return now > (this.sessionStart + (this.sessionTimeout - 5) * 1000);
95+
}
96+
8097
/**
8198
* Login to the API using the API key
8299
*/
83-
async loginWithApiKey(): Promise<string> {
84-
console.error("Logging in with API key");
85-
100+
async login(): Promise<string> {
86101
const loginResp = await APIClientBase.makeRequest(
87102
this.getHost(),
88103
"POST",
89104
"login",
90105
{ "api-key": this.apiKey },
91106
{ "Content-Type": "application/json" }
92107
);
108+
109+
this.sessionTimeout = loginResp.response["session-timeout"] || null;
110+
this.sessionStart = Date.now();
93111

94112
return loginResp.response.sid;
95113
}
@@ -124,33 +142,14 @@ export abstract class APIClientBase {
124142
if (method.toUpperCase() !== 'GET' && data !== undefined) {
125143
config.data = data;
126144
}
127-
128-
// Get settings to check if verbose mode is enabled
129-
const settings = (globalThis as any).cpMcpSettings as import('./settings').Settings | undefined;
130-
const verbose = settings?.verbose || false;
131-
132-
// Always log the URL for our debug API
133-
if (verbose) {
134-
console.error(`🌐 API Request: ${method} ${url}`);
135-
console.error('Headers: ' + JSON.stringify(headers));
136-
console.error('Params: ' + JSON.stringify(params));
137-
console.error('Data: ' + JSON.stringify(data));
138-
} else {
139-
console.error(`🌐 API Request: ${method} ${url}`);
140-
}
145+
146+
console.error(`API Request: ${method} ${url}`);
141147

142148
try {
143149
const response = await axios(config);
144-
145-
if (verbose) {
146-
console.error(`✅ API Response (${response.status}):`);
147-
console.error('Headers: ' + JSON.stringify(response.headers));
148-
console.error('Data: ' + JSON.stringify(response.data));
149-
}
150-
151150
return new ClientResponse(response.status, response.data as Record<string, any>);
152151
} catch (error: any) {
153-
if (verbose && error.response) {
152+
if (error.response) {
154153
console.error(`❌ API Error (${error.response.status}):`);
155154
console.error('Headers:', error.response.headers);
156155
console.error('Data:', error.response.data);
@@ -215,8 +214,8 @@ export class OnPremAPIClient extends APIClientBase {
215214
data: Record<string, any>,
216215
params?: Record<string, any>
217216
): Promise<ClientResponse> {
218-
if (!this.sid) {
219-
this.sid = await this.loginWithApiKey();
217+
if (!this.sid || this.isSessionExpired()) {
218+
this.sid = await this.login();
220219
}
221220

222221
// Allow self-signed certs for on-prem management servers
@@ -237,22 +236,15 @@ export class OnPremAPIClient extends APIClientBase {
237236
* Override loginWithApiKey to support both api-key and username/password authentication
238237
* and allow self-signed certificates
239238
*/
240-
async loginWithApiKey(): Promise<string> {
239+
async login(): Promise<string> {
241240
// Determine if we're using API key or username/password
242241
const isUsingApiKey = !!this.apiKey;
243242
const isUsingCredentials = !!(this.username && this.password);
244243

245244
if (!isUsingApiKey && !isUsingCredentials) {
246245
throw new Error("Authentication failed: No API key or username/password provided");
247246
}
248-
249-
// Log authentication method
250-
if (isUsingApiKey) {
251-
console.error("Logging in with API key (allowing self-signed certificates)");
252-
} else {
253-
console.error("Logging in with username/password (allowing self-signed certificates)");
254-
}
255-
247+
256248
// Allow self-signed certs for on-prem management servers
257249
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
258250

@@ -270,7 +262,11 @@ export class OnPremAPIClient extends APIClientBase {
270262
null,
271263
httpsAgent
272264
);
273-
265+
266+
this.sessionTimeout = loginResp.response["session-timeout"] || null;
267+
this.sessionStart = Date.now();
268+
this.sid = loginResp.response.sid;
269+
274270
return loginResp.response.sid;
275271
}
276272
}

packages/infra/src/settings.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Settings manager for MCP servers
2-
import * as z from 'zod';
2+
3+
import { nullOrEmpty } from './string-utils.js';
34

45
// Singleton instance for settings
56
let globalSettings: Settings | null = null;
@@ -64,25 +65,31 @@ export class Settings {
6465
this.managementPort = managementPort;
6566
this.origin = origin;
6667
this.verbose = verbose;
67-
68+
6869
this.validate();
6970
}
7071
/**
7172
* Validate the settings
7273
*/
74+
75+
7376
private validate(): void {
7477
// For S1C, API key is required
75-
if (this.s1cUrl && !this.apiKey) {
78+
if (!nullOrEmpty(this.s1cUrl) && nullOrEmpty(this.apiKey)) {
7679
throw new Error('API key is required for S1C (via --api-key or API_KEY env var)');
7780
}
7881

7982
// For on-prem, either API key or username/password is required
80-
if (this.managementHost && !this.apiKey && !(this.username && this.password)) {
83+
if (
84+
!nullOrEmpty(this.managementHost) &&
85+
nullOrEmpty(this.apiKey) &&
86+
(nullOrEmpty(this.username) || nullOrEmpty(this.password))
87+
) {
8188
throw new Error('Either API key or username/password are required for on-prem management (via CLI args or env vars)');
8289
}
8390

8491
// Need either management URL or management host
85-
if (!this.s1cUrl && !this.managementHost) {
92+
if (nullOrEmpty(this.s1cUrl) && nullOrEmpty(this.managementHost)) {
8693
// This validation is commented out in the Python code, so we'll do the same
8794
// throw new Error(
8895
// 'You must provide either management URL (cloud) or management host (on-prem) via CLI or env vars'

packages/infra/src/string-utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Utility for string checks
2+
export function nullOrEmpty(val?: string): boolean {
3+
return (
4+
val === undefined ||
5+
val === null ||
6+
(typeof val === 'string' && (val.trim() === '' || val === 'undefined' || val === 'null'))
7+
);
8+
}

0 commit comments

Comments
 (0)