fetchpet-mcp-server 0.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/README.md +181 -0
- package/build/index.integration-with-mock.js +166 -0
- package/build/index.js +129 -0
- package/package.json +53 -0
- package/shared/index.d.ts +5 -0
- package/shared/index.js +6 -0
- package/shared/logging.d.ts +20 -0
- package/shared/logging.js +34 -0
- package/shared/server.d.ts +135 -0
- package/shared/server.js +831 -0
- package/shared/tools.d.ts +8 -0
- package/shared/tools.js +403 -0
- package/shared/types.d.ts +105 -0
- package/shared/types.js +24 -0
package/README.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Fetch Pet MCP Server
|
|
2
|
+
|
|
3
|
+
MCP server for Fetch Pet insurance claims management using Playwright automation. Submit claims, track claim status, and view claim details including EOB and invoices.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Prepare Claims** - Fill out claim forms with validation (without submitting)
|
|
8
|
+
- **Submit Claims** - Actually submit prepared claims with explicit user confirmation
|
|
9
|
+
- **View All Claims** - See all claims (active and historical) in a single call
|
|
10
|
+
- **Claim Details** - Get detailed information including EOB and invoice downloads
|
|
11
|
+
|
|
12
|
+
## Tools
|
|
13
|
+
|
|
14
|
+
| Tool | Description |
|
|
15
|
+
| ------------------------- | ------------------------------------------------------------------- |
|
|
16
|
+
| `prepare_claim_to_submit` | Prepare a claim form for submission (validates but does NOT submit) |
|
|
17
|
+
| `submit_claim` | Submit a prepared claim (requires user confirmation token) |
|
|
18
|
+
| `get_claims` | Get all claims (both active/pending and historical/completed) |
|
|
19
|
+
| `get_claim_details` | Get detailed claim info including EOB and invoice downloads |
|
|
20
|
+
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
### Prerequisites
|
|
24
|
+
|
|
25
|
+
- Node.js 18+
|
|
26
|
+
- A Fetch Pet account (create one at [fetchpet.com](https://fetchpet.com))
|
|
27
|
+
|
|
28
|
+
### Environment Variables
|
|
29
|
+
|
|
30
|
+
| Variable | Required | Description | Default |
|
|
31
|
+
| ----------------------- | -------- | ---------------------------------- | ------------------------- |
|
|
32
|
+
| `FETCHPET_USERNAME` | Yes | Your Fetch Pet account email | - |
|
|
33
|
+
| `FETCHPET_PASSWORD` | Yes | Your Fetch Pet account password | - |
|
|
34
|
+
| `HEADLESS` | No | Run browser in headless mode | `true` |
|
|
35
|
+
| `TIMEOUT` | No | Browser operation timeout (ms) | `30000` |
|
|
36
|
+
| `FETCHPET_DOWNLOAD_DIR` | No | Directory to save downloaded files | `/tmp/fetchpet-downloads` |
|
|
37
|
+
|
|
38
|
+
### Claude Desktop
|
|
39
|
+
|
|
40
|
+
Make sure you have your Fetch Pet account credentials ready.
|
|
41
|
+
|
|
42
|
+
Then proceed to the setup instructions below. If this is your first time using MCP Servers, you'll want to make sure you have the [Claude Desktop application](https://claude.ai/download) and follow the [official MCP setup instructions](https://modelcontextprotocol.io/quickstart/user).
|
|
43
|
+
|
|
44
|
+
#### Manual Setup
|
|
45
|
+
|
|
46
|
+
You're going to need Node working on your machine so you can run `npx` commands in your terminal. If you don't have Node, you can install it from [nodejs.org](https://nodejs.org/en/download).
|
|
47
|
+
|
|
48
|
+
macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
49
|
+
|
|
50
|
+
Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
51
|
+
|
|
52
|
+
Modify your `claude_desktop_config.json` file to add the following:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"mcpServers": {
|
|
57
|
+
"fetchpet": {
|
|
58
|
+
"command": "npx",
|
|
59
|
+
"args": ["-y", "fetchpet-mcp-server"],
|
|
60
|
+
"env": {
|
|
61
|
+
"FETCHPET_USERNAME": "your-email@example.com",
|
|
62
|
+
"FETCHPET_PASSWORD": "your-password"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Restart Claude Desktop and you should be ready to go!
|
|
70
|
+
|
|
71
|
+
## Usage Examples
|
|
72
|
+
|
|
73
|
+
### Submit a new claim
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
"Submit a claim for my dog Buddy - I have an invoice from Test Vet Clinic for $150 dated January 15th for an annual checkup"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The assistant will:
|
|
80
|
+
|
|
81
|
+
1. Use `prepare_claim_to_submit` to fill out the form
|
|
82
|
+
2. Show you exactly what will be submitted
|
|
83
|
+
3. Ask for your explicit confirmation
|
|
84
|
+
4. Only then call `submit_claim` with the confirmation token
|
|
85
|
+
|
|
86
|
+
### View claims
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
"Show me my active claims"
|
|
90
|
+
"What claims are pending?"
|
|
91
|
+
"Show my claim history"
|
|
92
|
+
"What's the status of my recent claims?"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Get claim details
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
"Get details for claim ABC123"
|
|
99
|
+
"Download the EOB for my last claim"
|
|
100
|
+
"Show me the invoice for that claim"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## How It Works
|
|
104
|
+
|
|
105
|
+
This MCP server uses Playwright to automate a browser session with Fetch Pet:
|
|
106
|
+
|
|
107
|
+
1. **On server start**: Launches a browser in the background and logs into your Fetch Pet account
|
|
108
|
+
2. **Browser session persists**: All subsequent tool calls reuse the same logged-in session
|
|
109
|
+
3. **Smart navigation**: Tools navigate to the appropriate pages as needed
|
|
110
|
+
4. **Stealth mode**: Uses playwright-extra with stealth plugin to avoid bot detection
|
|
111
|
+
|
|
112
|
+
### Claim Submission Safety
|
|
113
|
+
|
|
114
|
+
The claim submission process is designed with safety in mind:
|
|
115
|
+
|
|
116
|
+
1. **`prepare_claim_to_submit`** fills out the form and validates everything but does NOT click submit
|
|
117
|
+
2. It returns a unique confirmation token
|
|
118
|
+
3. **`submit_claim`** requires this token, ensuring explicit user confirmation
|
|
119
|
+
4. Without the correct token, claims cannot be submitted
|
|
120
|
+
|
|
121
|
+
## Development
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# Install dependencies
|
|
125
|
+
npm run install-all
|
|
126
|
+
|
|
127
|
+
# Run in development mode
|
|
128
|
+
npm run dev
|
|
129
|
+
|
|
130
|
+
# Build
|
|
131
|
+
npm run build
|
|
132
|
+
|
|
133
|
+
# Run tests
|
|
134
|
+
npm test
|
|
135
|
+
|
|
136
|
+
# Run integration tests
|
|
137
|
+
npm run test:integration
|
|
138
|
+
|
|
139
|
+
# Run manual tests (requires real credentials)
|
|
140
|
+
npm run test:manual
|
|
141
|
+
|
|
142
|
+
# Lint
|
|
143
|
+
npm run lint
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Project Structure
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
fetchpet/
|
|
150
|
+
├── local/ # Local server implementation
|
|
151
|
+
│ └── src/
|
|
152
|
+
│ └── index.ts # Entry point with env validation
|
|
153
|
+
├── shared/ # Shared business logic
|
|
154
|
+
│ └── src/
|
|
155
|
+
│ ├── server.ts # FetchPetClient with Playwright automation
|
|
156
|
+
│ ├── tools.ts # MCP tool definitions
|
|
157
|
+
│ ├── types.ts # TypeScript types
|
|
158
|
+
│ └── logging.ts # Logging utilities
|
|
159
|
+
├── tests/ # Test suites
|
|
160
|
+
├── package.json # Root workspace config
|
|
161
|
+
└── README.md
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Security Notes
|
|
165
|
+
|
|
166
|
+
- Your Fetch Pet credentials are used only to log into your account
|
|
167
|
+
- The browser session runs locally on your machine
|
|
168
|
+
- No credentials are transmitted to any third-party services
|
|
169
|
+
- Consider using environment variables rather than hardcoding credentials
|
|
170
|
+
- Downloaded documents (EOB, invoices) are saved to the configured download directory
|
|
171
|
+
|
|
172
|
+
## Limitations
|
|
173
|
+
|
|
174
|
+
- Requires a valid Fetch Pet account
|
|
175
|
+
- Browser automation may occasionally fail if Fetch Pet updates their website
|
|
176
|
+
- Some operations require navigating between pages which takes time
|
|
177
|
+
- The website uses a React app, so dynamic content loading may require waits
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
MIT
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Integration test entry point that uses a mock client.
|
|
4
|
+
* This allows testing MCP server functionality without actual browser automation.
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync } from 'fs';
|
|
7
|
+
import { dirname, join } from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
10
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
11
|
+
import { createRegisterTools } from '../shared/tools.js';
|
|
12
|
+
import { logServerStart, logError } from '../shared/logging.js';
|
|
13
|
+
// Read version from package.json
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const packageJsonPath = join(__dirname, '..', 'package.json');
|
|
16
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
17
|
+
const VERSION = packageJson.version;
|
|
18
|
+
// =============================================================================
|
|
19
|
+
// MOCK CLIENT FOR INTEGRATION TESTS
|
|
20
|
+
// =============================================================================
|
|
21
|
+
class MockFetchPetClient {
|
|
22
|
+
mockToken = null;
|
|
23
|
+
async initialize() {
|
|
24
|
+
// Mock initialization - no actual browser
|
|
25
|
+
}
|
|
26
|
+
async prepareClaimToSubmit(petName, invoiceDate, invoiceAmount, providerName, claimDescription, _invoiceFilePath, _medicalRecordsPath) {
|
|
27
|
+
this.mockToken = 'mock-confirmation-token-12345';
|
|
28
|
+
return {
|
|
29
|
+
petName,
|
|
30
|
+
invoiceDate,
|
|
31
|
+
invoiceAmount,
|
|
32
|
+
providerName,
|
|
33
|
+
claimDescription,
|
|
34
|
+
isReadyToSubmit: true,
|
|
35
|
+
validationErrors: [],
|
|
36
|
+
confirmationMessage: `IMPORTANT: This claim has been prepared but NOT submitted yet.
|
|
37
|
+
|
|
38
|
+
To submit this claim, call submit_claim with confirmation_token: "${this.mockToken}"
|
|
39
|
+
|
|
40
|
+
Claim Details:
|
|
41
|
+
- Pet: ${petName}
|
|
42
|
+
- Invoice Date: ${invoiceDate}
|
|
43
|
+
- Amount: ${invoiceAmount}
|
|
44
|
+
- Provider: ${providerName}
|
|
45
|
+
- Description: ${claimDescription}
|
|
46
|
+
|
|
47
|
+
The user MUST explicitly confirm they want to submit this claim before calling submit_claim.`,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async submitClaim(confirmationToken) {
|
|
51
|
+
if (confirmationToken !== this.mockToken) {
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
message: 'Invalid or expired confirmation token',
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
this.mockToken = null;
|
|
58
|
+
return {
|
|
59
|
+
success: true,
|
|
60
|
+
message: 'Claim submitted successfully (mock)',
|
|
61
|
+
claimId: 'MOCK-CLAIM-001',
|
|
62
|
+
confirmationNumber: 'MOCK-CONF-12345',
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async getClaims() {
|
|
66
|
+
return [
|
|
67
|
+
{
|
|
68
|
+
claimId: 'MOCK-ACTIVE-001',
|
|
69
|
+
petName: 'Buddy',
|
|
70
|
+
claimDate: '2025-01-15',
|
|
71
|
+
claimAmount: '$250.00',
|
|
72
|
+
status: 'pending',
|
|
73
|
+
description: 'Annual checkup',
|
|
74
|
+
providerName: 'Mock Vet Clinic',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
claimId: 'MOCK-ACTIVE-002',
|
|
78
|
+
petName: 'Luna',
|
|
79
|
+
claimDate: '2025-01-20',
|
|
80
|
+
claimAmount: '$175.50',
|
|
81
|
+
status: 'processing',
|
|
82
|
+
description: 'Dental cleaning',
|
|
83
|
+
providerName: 'Pet Dental Care',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
claimId: 'MOCK-HIST-001',
|
|
87
|
+
petName: 'Buddy',
|
|
88
|
+
claimDate: '2024-12-01',
|
|
89
|
+
claimAmount: '$500.00',
|
|
90
|
+
status: 'approved',
|
|
91
|
+
description: 'Emergency surgery',
|
|
92
|
+
providerName: 'Emergency Vet Hospital',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
claimId: 'MOCK-HIST-002',
|
|
96
|
+
petName: 'Luna',
|
|
97
|
+
claimDate: '2024-11-15',
|
|
98
|
+
claimAmount: '$85.00',
|
|
99
|
+
status: 'paid',
|
|
100
|
+
description: 'Vaccinations',
|
|
101
|
+
providerName: 'Mock Vet Clinic',
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
}
|
|
105
|
+
async getClaimDetails(claimId) {
|
|
106
|
+
return {
|
|
107
|
+
claimId,
|
|
108
|
+
petName: 'Buddy',
|
|
109
|
+
claimDate: '2025-01-15',
|
|
110
|
+
claimAmount: '$250.00',
|
|
111
|
+
status: 'pending',
|
|
112
|
+
description: 'Annual checkup and vaccinations',
|
|
113
|
+
providerName: 'Mock Vet Clinic',
|
|
114
|
+
reimbursementAmount: '$200.00',
|
|
115
|
+
deductible: '$50.00',
|
|
116
|
+
copay: '$0.00',
|
|
117
|
+
eobSummary: 'EOB available for download',
|
|
118
|
+
invoiceSummary: 'Invoice available for download',
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
async getCurrentUrl() {
|
|
122
|
+
return 'https://my.fetchpet.com/dashboard';
|
|
123
|
+
}
|
|
124
|
+
async close() {
|
|
125
|
+
// Mock cleanup
|
|
126
|
+
}
|
|
127
|
+
getConfig() {
|
|
128
|
+
return {
|
|
129
|
+
username: 'mock@example.com',
|
|
130
|
+
password: 'mock-password',
|
|
131
|
+
headless: true,
|
|
132
|
+
timeout: 30000,
|
|
133
|
+
downloadDir: '/tmp/mock-downloads',
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// =============================================================================
|
|
138
|
+
// MAIN ENTRY POINT
|
|
139
|
+
// =============================================================================
|
|
140
|
+
async function main() {
|
|
141
|
+
const server = new Server({
|
|
142
|
+
name: 'fetchpet-mcp-server',
|
|
143
|
+
version: VERSION,
|
|
144
|
+
}, {
|
|
145
|
+
capabilities: {
|
|
146
|
+
tools: {},
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
// Create mock client
|
|
150
|
+
const mockClient = new MockFetchPetClient();
|
|
151
|
+
// Register tools with mock client factory
|
|
152
|
+
const registerTools = createRegisterTools(() => mockClient, async () => {
|
|
153
|
+
await mockClient.initialize();
|
|
154
|
+
return mockClient;
|
|
155
|
+
});
|
|
156
|
+
registerTools(server);
|
|
157
|
+
// Start server with stdio transport
|
|
158
|
+
const transport = new StdioServerTransport();
|
|
159
|
+
await server.connect(transport);
|
|
160
|
+
logServerStart('Fetch Pet (Mock Mode)');
|
|
161
|
+
}
|
|
162
|
+
// Run the server
|
|
163
|
+
main().catch((error) => {
|
|
164
|
+
logError('main', error);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
});
|
package/build/index.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
6
|
+
import { createMCPServer } from '../shared/index.js';
|
|
7
|
+
import { logServerStart, logError, logWarning } from '../shared/logging.js';
|
|
8
|
+
// Read version from package.json
|
|
9
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const packageJsonPath = join(__dirname, '..', 'package.json');
|
|
11
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
12
|
+
const VERSION = packageJson.version;
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// ENVIRONMENT VALIDATION
|
|
15
|
+
// =============================================================================
|
|
16
|
+
function validateEnvironment() {
|
|
17
|
+
const required = [
|
|
18
|
+
{
|
|
19
|
+
name: 'FETCHPET_USERNAME',
|
|
20
|
+
description: 'Your Fetch Pet account email address',
|
|
21
|
+
example: 'user@example.com',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'FETCHPET_PASSWORD',
|
|
25
|
+
description: 'Your Fetch Pet account password',
|
|
26
|
+
example: 'your-password',
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
const optional = [
|
|
30
|
+
{
|
|
31
|
+
name: 'HEADLESS',
|
|
32
|
+
description: 'Run browser in headless mode (true/false)',
|
|
33
|
+
defaultValue: 'true',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'TIMEOUT',
|
|
37
|
+
description: 'Default timeout for browser operations in milliseconds',
|
|
38
|
+
defaultValue: '30000',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'FETCHPET_DOWNLOAD_DIR',
|
|
42
|
+
description: 'Directory to save downloaded documents (EOB, invoices)',
|
|
43
|
+
defaultValue: '/tmp/fetchpet-downloads',
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
const missing = required.filter(({ name }) => !process.env[name]);
|
|
47
|
+
if (missing.length > 0) {
|
|
48
|
+
logError('validateEnvironment', 'Missing required environment variables:');
|
|
49
|
+
missing.forEach(({ name, description, example }) => {
|
|
50
|
+
console.error(` - ${name}: ${description}`);
|
|
51
|
+
console.error(` Example: ${example}`);
|
|
52
|
+
});
|
|
53
|
+
if (optional.length > 0) {
|
|
54
|
+
console.error('\nOptional environment variables:');
|
|
55
|
+
optional.forEach(({ name, description, defaultValue }) => {
|
|
56
|
+
const defaultStr = defaultValue ? ` (default: ${defaultValue})` : '';
|
|
57
|
+
console.error(` - ${name}: ${description}${defaultStr}`);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
console.error('\n----------------------------------------');
|
|
61
|
+
console.error('Please set the required environment variables and try again.');
|
|
62
|
+
console.error('\nExample commands:');
|
|
63
|
+
missing.forEach(({ name, example }) => {
|
|
64
|
+
console.error(` export ${name}="${example}"`);
|
|
65
|
+
});
|
|
66
|
+
console.error('----------------------------------------\n');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
// Log configuration
|
|
70
|
+
const headless = process.env.HEADLESS !== 'false';
|
|
71
|
+
const timeout = process.env.TIMEOUT || '30000';
|
|
72
|
+
const downloadDir = process.env.FETCHPET_DOWNLOAD_DIR || '/tmp/fetchpet-downloads';
|
|
73
|
+
if (!headless) {
|
|
74
|
+
logWarning('config', 'Running in non-headless mode - browser window will be visible');
|
|
75
|
+
}
|
|
76
|
+
if (process.env.TIMEOUT) {
|
|
77
|
+
logWarning('config', `Custom timeout configured: ${timeout}ms`);
|
|
78
|
+
}
|
|
79
|
+
if (process.env.FETCHPET_DOWNLOAD_DIR) {
|
|
80
|
+
logWarning('config', `Custom download directory: ${downloadDir}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// =============================================================================
|
|
84
|
+
// MAIN ENTRY POINT
|
|
85
|
+
// =============================================================================
|
|
86
|
+
async function main() {
|
|
87
|
+
// Step 1: Validate environment variables
|
|
88
|
+
validateEnvironment();
|
|
89
|
+
// Step 2: Create server using factory
|
|
90
|
+
const { server, registerHandlers, cleanup, startBackgroundLogin } = createMCPServer({
|
|
91
|
+
version: VERSION,
|
|
92
|
+
});
|
|
93
|
+
// Step 3: Register all handlers (tools)
|
|
94
|
+
await registerHandlers(server);
|
|
95
|
+
// Step 4: Set up graceful shutdown
|
|
96
|
+
const handleShutdown = async () => {
|
|
97
|
+
logWarning('shutdown', 'Received shutdown signal, closing browser...');
|
|
98
|
+
await cleanup();
|
|
99
|
+
process.exit(0);
|
|
100
|
+
};
|
|
101
|
+
process.on('SIGINT', handleShutdown);
|
|
102
|
+
process.on('SIGTERM', handleShutdown);
|
|
103
|
+
// Step 5: Start server with stdio transport
|
|
104
|
+
const transport = new StdioServerTransport();
|
|
105
|
+
await server.connect(transport);
|
|
106
|
+
logServerStart('Fetch Pet');
|
|
107
|
+
// Step 6: Start background login process
|
|
108
|
+
// This kicks off Playwright and performs login without blocking the stdio connection.
|
|
109
|
+
// If login fails, the server will close with an error.
|
|
110
|
+
logWarning('login', 'Starting background login to Fetch Pet...');
|
|
111
|
+
startBackgroundLogin((error) => {
|
|
112
|
+
// Login failed - log error and exit
|
|
113
|
+
logError('login', `Background login failed: ${error.message}`);
|
|
114
|
+
logError('login', 'Server shutting down due to authentication failure.');
|
|
115
|
+
// Clean up and exit with error
|
|
116
|
+
cleanup()
|
|
117
|
+
.catch((cleanupError) => {
|
|
118
|
+
logError('cleanup', `Error during cleanup: ${cleanupError}`);
|
|
119
|
+
})
|
|
120
|
+
.finally(() => {
|
|
121
|
+
process.exit(1);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
// Run the server
|
|
126
|
+
main().catch((error) => {
|
|
127
|
+
logError('main', error);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fetchpet-mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Fetch Pet insurance claims management with Playwright automation",
|
|
5
|
+
"main": "build/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"fetchpet-mcp-server": "./build/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"build/**/*.js",
|
|
12
|
+
"build/**/*.d.ts",
|
|
13
|
+
"shared/**/*.js",
|
|
14
|
+
"shared/**/*.d.ts",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc && npm run build:integration",
|
|
19
|
+
"build:integration": "tsc -p tsconfig.integration.json",
|
|
20
|
+
"start": "node build/index.js",
|
|
21
|
+
"dev": "tsx src/index.ts",
|
|
22
|
+
"predev": "cd ../shared && npm run build && cd ../local && node setup-dev.js",
|
|
23
|
+
"prebuild": "cd ../shared && npm run build && cd ../local && node setup-dev.js",
|
|
24
|
+
"prepublishOnly": "node prepare-publish.js && node ../scripts/prepare-npm-readme.js",
|
|
25
|
+
"lint": "eslint . --ext .ts,.tsx",
|
|
26
|
+
"lint:fix": "eslint . --ext .ts,.tsx --fix",
|
|
27
|
+
"format": "prettier --write .",
|
|
28
|
+
"format:check": "prettier --check .",
|
|
29
|
+
"stage-publish": "npm version"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@modelcontextprotocol/sdk": "^1.19.1",
|
|
33
|
+
"playwright": "^1.49.1",
|
|
34
|
+
"playwright-extra": "^4.3.6",
|
|
35
|
+
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
|
36
|
+
"zod": "^3.24.1"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^22.10.6",
|
|
40
|
+
"tsx": "^4.19.4",
|
|
41
|
+
"typescript": "^5.7.3"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"mcp",
|
|
45
|
+
"fetch",
|
|
46
|
+
"pet",
|
|
47
|
+
"insurance",
|
|
48
|
+
"claims",
|
|
49
|
+
"playwright"
|
|
50
|
+
],
|
|
51
|
+
"author": "PulseMCP",
|
|
52
|
+
"license": "MIT"
|
|
53
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createMCPServer, FetchPetClient, type IFetchPetClient, type ClientFactory, type CreateMCPServerOptions, } from './server.js';
|
|
2
|
+
export { createRegisterTools } from './tools.js';
|
|
3
|
+
export type { Claim, ClaimDetails, ClaimSubmissionData, ClaimSubmissionResult, FetchPetConfig, } from './types.js';
|
|
4
|
+
export { logServerStart, logError, logWarning, logDebug } from './logging.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
package/shared/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Core server exports
|
|
2
|
+
export { createMCPServer, FetchPetClient, } from './server.js';
|
|
3
|
+
// Tools exports
|
|
4
|
+
export { createRegisterTools } from './tools.js';
|
|
5
|
+
// Logging exports (re-exported for convenience)
|
|
6
|
+
export { logServerStart, logError, logWarning, logDebug } from './logging.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging utilities for consistent output across MCP servers
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Log server startup message
|
|
6
|
+
*/
|
|
7
|
+
export declare function logServerStart(serverName: string, transport?: string): void;
|
|
8
|
+
/**
|
|
9
|
+
* Log an error with context
|
|
10
|
+
*/
|
|
11
|
+
export declare function logError(context: string, error: unknown): void;
|
|
12
|
+
/**
|
|
13
|
+
* Log a warning
|
|
14
|
+
*/
|
|
15
|
+
export declare function logWarning(context: string, message: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* Log debug information (only in development)
|
|
18
|
+
*/
|
|
19
|
+
export declare function logDebug(context: string, message: string): void;
|
|
20
|
+
//# sourceMappingURL=logging.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging utilities for consistent output across MCP servers
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Log server startup message
|
|
6
|
+
*/
|
|
7
|
+
export function logServerStart(serverName, transport = 'stdio') {
|
|
8
|
+
console.error(`MCP server ${serverName} running on ${transport}`);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Log an error with context
|
|
12
|
+
*/
|
|
13
|
+
export function logError(context, error) {
|
|
14
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15
|
+
const stack = error instanceof Error ? error.stack : undefined;
|
|
16
|
+
console.error(`[ERROR] ${context}: ${message}`);
|
|
17
|
+
if (stack) {
|
|
18
|
+
console.error(stack);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Log a warning
|
|
23
|
+
*/
|
|
24
|
+
export function logWarning(context, message) {
|
|
25
|
+
console.error(`[WARN] ${context}: ${message}`);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Log debug information (only in development)
|
|
29
|
+
*/
|
|
30
|
+
export function logDebug(context, message) {
|
|
31
|
+
if (process.env.NODE_ENV === 'development' || process.env.DEBUG) {
|
|
32
|
+
console.error(`[DEBUG] ${context}: ${message}`);
|
|
33
|
+
}
|
|
34
|
+
}
|