@striderlabs/mcp-gap 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/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@striderlabs/mcp-gap",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for Gap Inc. — search products, manage cart, track orders, and shop Gap, Old Navy, Banana Republic, and Athleta with AI agents",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "striderlabs-mcp-gap": "dist/index.js"
8
+ },
9
+ "type": "module",
10
+ "scripts": {
11
+ "build": "node build.js",
12
+ "start": "node dist/index.js",
13
+ "typecheck": "tsc --noEmit"
14
+ },
15
+ "keywords": [
16
+ "mcp",
17
+ "gap",
18
+ "old-navy",
19
+ "banana-republic",
20
+ "athleta",
21
+ "fashion",
22
+ "shopping",
23
+ "retail",
24
+ "ai-agent",
25
+ "strider",
26
+ "model-context-protocol",
27
+ "browser-automation"
28
+ ],
29
+ "author": "Strider Labs <hello@striderlabs.ai>",
30
+ "license": "MIT",
31
+ "homepage": "https://striderlabs.ai",
32
+ "dependencies": {
33
+ "@modelcontextprotocol/sdk": "^1.0.0",
34
+ "patchright": "^1.58.2"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^20.11.0",
38
+ "esbuild": "^0.24.0",
39
+ "typescript": "^5.3.3"
40
+ },
41
+ "mcpName": "io.github.striderlabs/gap"
42
+ }
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.striderlabs/gap",
4
+ "description": "Gap Inc. MCP server — search and shop Gap, Old Navy, Banana Republic, and Athleta. Manage cart, orders, rewards, and returns. By Strider Labs.",
5
+ "repository": {
6
+ "url": "https://github.com/striderlabs/mcp-gap",
7
+ "source": "github"
8
+ },
9
+ "version": "0.1.0",
10
+ "packages": [
11
+ {
12
+ "registryType": "npm",
13
+ "identifier": "@striderlabs/mcp-gap",
14
+ "version": "0.1.0",
15
+ "transport": {
16
+ "type": "stdio"
17
+ }
18
+ }
19
+ ]
20
+ }
package/src/auth.ts ADDED
@@ -0,0 +1,82 @@
1
+ import { BrowserContext } from 'patchright';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import os from 'os';
5
+
6
+ export interface SessionInfo {
7
+ isLoggedIn: boolean;
8
+ userEmail?: string;
9
+ userName?: string;
10
+ lastUpdated: string;
11
+ gapCashBalance?: string;
12
+ rewardsPoints?: string;
13
+ }
14
+
15
+ function getConfigDir(): string {
16
+ return path.join(os.homedir(), '.strider', 'gap');
17
+ }
18
+
19
+ function getCookiesPath(): string {
20
+ return path.join(getConfigDir(), 'cookies.json');
21
+ }
22
+
23
+ function getSessionPath(): string {
24
+ return path.join(getConfigDir(), 'session.json');
25
+ }
26
+
27
+ function ensureConfigDir(): void {
28
+ const dir = getConfigDir();
29
+ if (!fs.existsSync(dir)) {
30
+ fs.mkdirSync(dir, { recursive: true });
31
+ }
32
+ }
33
+
34
+ export async function saveCookies(context: BrowserContext): Promise<void> {
35
+ ensureConfigDir();
36
+ const cookies = await context.cookies();
37
+ fs.writeFileSync(getCookiesPath(), JSON.stringify(cookies, null, 2));
38
+ }
39
+
40
+ export async function loadCookies(context: BrowserContext): Promise<boolean> {
41
+ const cookiesPath = getCookiesPath();
42
+ if (!fs.existsSync(cookiesPath)) return false;
43
+
44
+ try {
45
+ const data = fs.readFileSync(cookiesPath, 'utf-8');
46
+ const cookies = JSON.parse(data);
47
+ const now = Date.now() / 1000;
48
+ const valid = cookies.filter((c: { expires?: number }) => !c.expires || c.expires > now);
49
+ if (valid.length === 0) return false;
50
+ await context.addCookies(valid);
51
+ return true;
52
+ } catch {
53
+ return false;
54
+ }
55
+ }
56
+
57
+ export function saveSessionInfo(info: SessionInfo): void {
58
+ ensureConfigDir();
59
+ fs.writeFileSync(getSessionPath(), JSON.stringify(info, null, 2));
60
+ }
61
+
62
+ export function loadSessionInfo(): SessionInfo | null {
63
+ const sessionPath = getSessionPath();
64
+ if (!fs.existsSync(sessionPath)) return null;
65
+ try {
66
+ return JSON.parse(fs.readFileSync(sessionPath, 'utf-8'));
67
+ } catch {
68
+ return null;
69
+ }
70
+ }
71
+
72
+ export function clearAuthData(): void {
73
+ const dir = getConfigDir();
74
+ const cookiesPath = getCookiesPath();
75
+ const sessionPath = getSessionPath();
76
+ if (fs.existsSync(cookiesPath)) fs.unlinkSync(cookiesPath);
77
+ if (fs.existsSync(sessionPath)) fs.unlinkSync(sessionPath);
78
+ }
79
+
80
+ export function hasSavedCookies(): boolean {
81
+ return fs.existsSync(getCookiesPath());
82
+ }