easyeda-mcp-pro 0.4.0 → 0.5.2

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.
Files changed (171) hide show
  1. package/README.md +68 -24
  2. package/dist/bom-quality/adapter.d.ts +90 -0
  3. package/dist/bom-quality/adapter.js +295 -0
  4. package/dist/bom-quality/adapter.js.map +1 -0
  5. package/dist/bom-quality/index.d.ts +10 -0
  6. package/dist/bom-quality/index.js +9 -0
  7. package/dist/bom-quality/index.js.map +1 -0
  8. package/dist/bom-quality/quality.d.ts +28 -0
  9. package/dist/bom-quality/quality.js +179 -0
  10. package/dist/bom-quality/quality.js.map +1 -0
  11. package/dist/bom-quality/types.d.ts +94 -0
  12. package/dist/bom-quality/types.js +12 -0
  13. package/dist/bom-quality/types.js.map +1 -0
  14. package/dist/bridge/manager.d.ts +41 -0
  15. package/dist/bridge/manager.js +333 -51
  16. package/dist/bridge/manager.js.map +1 -1
  17. package/dist/bridge/protocol.d.ts +47 -1
  18. package/dist/bridge/protocol.js +42 -1
  19. package/dist/bridge/protocol.js.map +1 -1
  20. package/dist/bridge/types.d.ts +6 -0
  21. package/dist/bridge/types.js +6 -0
  22. package/dist/bridge/types.js.map +1 -1
  23. package/dist/catalog/errors.d.ts +49 -0
  24. package/dist/catalog/errors.js +60 -0
  25. package/dist/catalog/errors.js.map +1 -0
  26. package/dist/catalog/index.d.ts +15 -0
  27. package/dist/catalog/index.js +17 -0
  28. package/dist/catalog/index.js.map +1 -0
  29. package/dist/catalog/schema.d.ts +268 -0
  30. package/dist/catalog/schema.js +245 -0
  31. package/dist/catalog/schema.js.map +1 -0
  32. package/dist/catalog/starter.d.ts +159 -0
  33. package/dist/catalog/starter.js +579 -0
  34. package/dist/catalog/starter.js.map +1 -0
  35. package/dist/catalog/validation.d.ts +48 -0
  36. package/dist/catalog/validation.js +263 -0
  37. package/dist/catalog/validation.js.map +1 -0
  38. package/dist/circuit/circuit-ir.d.ts +460 -0
  39. package/dist/circuit/circuit-ir.js +292 -0
  40. package/dist/circuit/circuit-ir.js.map +1 -0
  41. package/dist/circuit/compiler.d.ts +55 -0
  42. package/dist/circuit/compiler.js +197 -0
  43. package/dist/circuit/compiler.js.map +1 -0
  44. package/dist/circuit/design-intent.d.ts +94 -0
  45. package/dist/circuit/design-intent.js +118 -0
  46. package/dist/circuit/design-intent.js.map +1 -0
  47. package/dist/circuit/errors.d.ts +50 -0
  48. package/dist/circuit/errors.js +61 -0
  49. package/dist/circuit/errors.js.map +1 -0
  50. package/dist/circuit/index.d.ts +17 -0
  51. package/dist/circuit/index.js +18 -0
  52. package/dist/circuit/index.js.map +1 -0
  53. package/dist/circuit/types.d.ts +186 -0
  54. package/dist/circuit/types.js +123 -0
  55. package/dist/circuit/types.js.map +1 -0
  56. package/dist/cli/auto-setup.d.ts +1 -8
  57. package/dist/cli/auto-setup.js +10 -178
  58. package/dist/cli/auto-setup.js.map +1 -1
  59. package/dist/cli/client-definitions.d.ts +34 -0
  60. package/dist/cli/client-definitions.js +194 -0
  61. package/dist/cli/client-definitions.js.map +1 -0
  62. package/dist/cli/local-setup.js +2 -2
  63. package/dist/cli/local-setup.js.map +1 -1
  64. package/dist/config/env.d.ts +6 -1
  65. package/dist/config/env.js +93 -5
  66. package/dist/config/env.js.map +1 -1
  67. package/dist/config/version.d.ts +1 -1
  68. package/dist/config/version.js +1 -1
  69. package/dist/export-manifest/errors.d.ts +55 -0
  70. package/dist/export-manifest/errors.js +69 -0
  71. package/dist/export-manifest/errors.js.map +1 -0
  72. package/dist/export-manifest/index.d.ts +10 -0
  73. package/dist/export-manifest/index.js +9 -0
  74. package/dist/export-manifest/index.js.map +1 -0
  75. package/dist/export-manifest/types.d.ts +170 -0
  76. package/dist/export-manifest/types.js +36 -0
  77. package/dist/export-manifest/types.js.map +1 -0
  78. package/dist/export-manifest/validation.d.ts +39 -0
  79. package/dist/export-manifest/validation.js +298 -0
  80. package/dist/export-manifest/validation.js.map +1 -0
  81. package/dist/index.js +7 -0
  82. package/dist/index.js.map +1 -1
  83. package/dist/net-validation/errors.d.ts +89 -0
  84. package/dist/net-validation/errors.js +69 -0
  85. package/dist/net-validation/errors.js.map +1 -0
  86. package/dist/net-validation/fixtures.d.ts +38 -0
  87. package/dist/net-validation/fixtures.js +215 -0
  88. package/dist/net-validation/fixtures.js.map +1 -0
  89. package/dist/net-validation/index.d.ts +10 -0
  90. package/dist/net-validation/index.js +9 -0
  91. package/dist/net-validation/index.js.map +1 -0
  92. package/dist/net-validation/schema.d.ts +118 -0
  93. package/dist/net-validation/schema.js +140 -0
  94. package/dist/net-validation/schema.js.map +1 -0
  95. package/dist/net-validation/validation.d.ts +45 -0
  96. package/dist/net-validation/validation.js +369 -0
  97. package/dist/net-validation/validation.js.map +1 -0
  98. package/dist/pcb-constraints/errors.d.ts +39 -0
  99. package/dist/pcb-constraints/errors.js +133 -0
  100. package/dist/pcb-constraints/errors.js.map +1 -0
  101. package/dist/pcb-constraints/index.d.ts +9 -0
  102. package/dist/pcb-constraints/index.js +9 -0
  103. package/dist/pcb-constraints/index.js.map +1 -0
  104. package/dist/pcb-constraints/types.d.ts +102 -0
  105. package/dist/pcb-constraints/types.js +7 -0
  106. package/dist/pcb-constraints/types.js.map +1 -0
  107. package/dist/pcb-constraints/validation.d.ts +70 -0
  108. package/dist/pcb-constraints/validation.js +309 -0
  109. package/dist/pcb-constraints/validation.js.map +1 -0
  110. package/dist/server/factory.js +2 -0
  111. package/dist/server/factory.js.map +1 -1
  112. package/dist/server/transports/http.d.ts +20 -1
  113. package/dist/server/transports/http.js +156 -34
  114. package/dist/server/transports/http.js.map +1 -1
  115. package/dist/storage/database.d.ts +25 -0
  116. package/dist/storage/database.js +126 -51
  117. package/dist/storage/database.js.map +1 -1
  118. package/dist/tools/{L0_diagnostics.d.ts → L0_diagnostics_api.d.ts} +2 -2
  119. package/dist/tools/L0_diagnostics_api.js +152 -0
  120. package/dist/tools/L0_diagnostics_api.js.map +1 -0
  121. package/dist/tools/L0_diagnostics_core.d.ts +6 -0
  122. package/dist/tools/{L0_diagnostics.js → L0_diagnostics_core.js} +50 -124
  123. package/dist/tools/L0_diagnostics_core.js.map +1 -0
  124. package/dist/tools/L1_board.js +20 -4
  125. package/dist/tools/L1_board.js.map +1 -1
  126. package/dist/tools/{L1_bom.d.ts → L1_bom_core.d.ts} +2 -2
  127. package/dist/tools/{L1_bom.js → L1_bom_core.js} +21 -101
  128. package/dist/tools/L1_bom_core.js.map +1 -0
  129. package/dist/tools/{L1_schematic.d.ts → L1_bom_sourcing.d.ts} +2 -2
  130. package/dist/tools/L1_bom_sourcing.js +265 -0
  131. package/dist/tools/L1_bom_sourcing.js.map +1 -0
  132. package/dist/tools/L1_drc_erc.js +15 -3
  133. package/dist/tools/L1_drc_erc.js.map +1 -1
  134. package/dist/tools/L1_export.js +20 -4
  135. package/dist/tools/L1_export.js.map +1 -1
  136. package/dist/tools/L1_pcb_constraints.d.ts +6 -0
  137. package/dist/tools/L1_pcb_constraints.js +234 -0
  138. package/dist/tools/L1_pcb_constraints.js.map +1 -0
  139. package/dist/tools/L1_pcb_write.js +26 -12
  140. package/dist/tools/L1_pcb_write.js.map +1 -1
  141. package/dist/tools/L1_schematic_read.d.ts +6 -0
  142. package/dist/tools/{L1_schematic.js → L1_schematic_read.js} +125 -194
  143. package/dist/tools/L1_schematic_read.js.map +1 -0
  144. package/dist/tools/L1_schematic_write.d.ts +6 -0
  145. package/dist/tools/L1_schematic_write.js +516 -0
  146. package/dist/tools/L1_schematic_write.js.map +1 -0
  147. package/dist/tools/register.js +15 -7
  148. package/dist/tools/register.js.map +1 -1
  149. package/dist/tools/registry.d.ts +41 -7
  150. package/dist/tools/registry.js +95 -25
  151. package/dist/tools/registry.js.map +1 -1
  152. package/dist/tools/types.d.ts +16 -0
  153. package/dist/utils/logger.d.ts +1 -1
  154. package/dist/utils/logger.js +1 -1
  155. package/dist/utils/logger.js.map +1 -1
  156. package/dist/vendors/base-http-client.d.ts +48 -0
  157. package/dist/vendors/base-http-client.js +75 -0
  158. package/dist/vendors/base-http-client.js.map +1 -0
  159. package/dist/vendors/digikey/client.js +10 -19
  160. package/dist/vendors/digikey/client.js.map +1 -1
  161. package/dist/vendors/jlcpcb/client.js +41 -70
  162. package/dist/vendors/jlcpcb/client.js.map +1 -1
  163. package/dist/vendors/lcsc/client.js +5 -18
  164. package/dist/vendors/lcsc/client.js.map +1 -1
  165. package/dist/vendors/mouser/client.js +4 -12
  166. package/dist/vendors/mouser/client.js.map +1 -1
  167. package/easyeda-bridge-extension.eext +0 -0
  168. package/package.json +11 -10
  169. package/dist/tools/L0_diagnostics.js.map +0 -1
  170. package/dist/tools/L1_bom.js.map +0 -1
  171. package/dist/tools/L1_schematic.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/pcb-constraints/validation.ts"],"names":[],"mappings":"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"}
@@ -55,6 +55,8 @@ export async function createServer(config) {
55
55
  config: {
56
56
  bridgeTimeoutMs: config.BRIDGE_TIMEOUT_MS,
57
57
  artifactDir: config.ARTIFACT_DIR,
58
+ bridgeHost: config.BRIDGE_HOST,
59
+ bridgePort: config.BRIDGE_PORT,
58
60
  },
59
61
  vendors: {
60
62
  lcsc: lcscClient,
@@ -1 +1 @@
1
- {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/server/factory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/server/factory.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type Express } from 'express';
1
+ import { type Express, type Request, type Response, type NextFunction } from 'express';
2
2
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
3
3
  import { type EnvConfig } from '../../config/env.js';
4
4
  export interface HttpTransportInstance {
@@ -7,4 +7,23 @@ export interface HttpTransportInstance {
7
7
  start: () => Promise<void>;
8
8
  close: () => Promise<void>;
9
9
  }
10
+ /** Check whether the given host is a loopback address. */
11
+ export declare function isLoopback(host: string): boolean;
12
+ /**
13
+ * Parse a comma-separated origin allowlist string into a Set.
14
+ * Empty string returns an empty set. '*' returns a set containing '*' only.
15
+ */
16
+ export declare function parseOriginAllowlist(raw: string): Set<string>;
17
+ /**
18
+ * Create middleware for origin validation and CORS handling.
19
+ *
20
+ * - DNS rebinding protection: validates the Host header matches the configured
21
+ * HTTP_HOST when running on a non-loopback address.
22
+ * - Origin validation: rejects requests whose `Origin` is not in the allowlist.
23
+ * - CORS preflight: responds with appropriate headers for OPTIONS requests.
24
+ * - No-origin requests (non-browser clients) are always allowed.
25
+ */
26
+ export declare function createOriginValidator(config: EnvConfig): (req: Request, res: Response, next: NextFunction) => void;
27
+ /** CORS preflight handler for OPTIONS requests. */
28
+ export declare function handleCorsPreflight(req: Request, res: Response, next: NextFunction): void;
10
29
  export declare function createHttpTransport(config: EnvConfig): HttpTransportInstance;
@@ -1,8 +1,11 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { createMcpExpressApp } from '@modelcontextprotocol/sdk/server/express.js';
3
3
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
4
+ import { createRemoteJWKSet, jwtVerify } from 'jose';
4
5
  import { SERVER_VERSION } from '../../config/version.js';
5
6
  import { getLogger } from '../../utils/logger.js';
7
+ /** Known loopback host values used for default origin policy. */
8
+ const LOOPBACK_ORIGINS = new Set(['http://127.0.0.1', 'http://localhost', 'http://::1', 'null']);
6
9
  function createRateLimiter(windowMs, maxRequests) {
7
10
  const store = new Map();
8
11
  const CLEANUP_THRESHOLD = 1000;
@@ -31,56 +34,184 @@ function createRateLimiter(windowMs, maxRequests) {
31
34
  next();
32
35
  };
33
36
  }
37
+ /**
38
+ * Supported token type hints (typ claim).
39
+ * We accept JWT by default and only reject tokens with an explicit non-JWT typ.
40
+ */
41
+ const SUPPORTED_TOKEN_TYPES = new Set(['JWT', undefined]);
42
+ /** Structured error responses for token validation failures. */
43
+ function tokenError(res, message, code = 'invalid_token') {
44
+ res.status(401).json({ error: message, code });
45
+ }
34
46
  function validateOAuthToken(config) {
35
47
  if (!config.OAUTH_ENABLED) {
36
48
  return (_req, _res, next) => next();
37
49
  }
38
- let JWKSet = null;
50
+ // The config validator already ensures OAUTH_JWKS_URI is present when OAuth is enabled.
51
+ // We cache the JWKSet for the lifetime of the server.
52
+ const JWKSet = createRemoteJWKSet(new URL(config.OAUTH_JWKS_URI));
39
53
  return (req, res, next) => {
54
+ // ── 1. Extract Bearer token ───────────────────────────────────────────
40
55
  const auth = req.headers.authorization;
41
56
  if (!auth || !auth.startsWith('Bearer ')) {
42
- res.status(401).json({ error: 'Missing or invalid Authorization header' });
57
+ tokenError(res, 'Missing or invalid Authorization header', 'missing_auth');
43
58
  return;
44
59
  }
45
60
  const token = auth.slice(7);
46
61
  if (!token) {
47
- res.status(401).json({ error: 'Empty Bearer token' });
62
+ tokenError(res, 'Empty Bearer token', 'empty_token');
48
63
  return;
49
64
  }
50
- if (!config.OAUTH_JWKS_URI) {
51
- const configured = config.OAUTH_REQUIRED_SCOPES || 'easyeda:read';
52
- if (token.length < 8) {
53
- res.status(401).json({ error: 'Invalid token format' });
65
+ // ── 2. Verify JWT ─────────────────────────────────────────────────────
66
+ jwtVerify(token, JWKSet, {
67
+ issuer: config.OAUTH_ISSUER || undefined,
68
+ audience: config.OAUTH_AUDIENCE || undefined,
69
+ algorithms: ['RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512'],
70
+ })
71
+ .then(({ payload, protectedHeader }) => {
72
+ // Validate token type (typ) — it lives in the protected header per JWT spec
73
+ const typ = protectedHeader.typ;
74
+ if (typ !== undefined && !SUPPORTED_TOKEN_TYPES.has(typ)) {
75
+ tokenError(res, `Unsupported token type: ${typ}`, 'unsupported_token_type');
54
76
  return;
55
77
  }
56
- res.locals.scope = configured;
78
+ res.locals.claims = payload;
79
+ next();
80
+ })
81
+ .catch((err) => {
82
+ const msg = err instanceof Error ? err.message : String(err);
83
+ getLogger().warn({ err: msg }, 'OAuth token validation failed');
84
+ // Map jose errors to user-friendly messages
85
+ // jose error examples:
86
+ // '"exp" claim timestamp check failed' → token_expired
87
+ // '"iss" claim mismatch' → invalid_issuer
88
+ // '"aud" claim mismatch' → invalid_audience
89
+ // 'signature verification failed' → invalid_signature
90
+ if (/["']exp["']/.test(msg) || /expired|timestamp/i.test(msg)) {
91
+ tokenError(res, 'Token has expired', 'token_expired');
92
+ }
93
+ else if (/["']iss["']/.test(msg) || /issuer/i.test(msg)) {
94
+ tokenError(res, 'Invalid token issuer', 'invalid_issuer');
95
+ }
96
+ else if (/["']aud["']/.test(msg) || /audience/i.test(msg)) {
97
+ tokenError(res, 'Invalid token audience', 'invalid_audience');
98
+ }
99
+ else if (/signature|key|JWT|JWS|malformed|parse/i.test(msg)) {
100
+ tokenError(res, 'Invalid token signature', 'invalid_signature');
101
+ }
102
+ else {
103
+ tokenError(res, 'Token validation failed', 'token_validation_failed');
104
+ }
105
+ });
106
+ };
107
+ }
108
+ /** Check whether the given host is a loopback address. */
109
+ export function isLoopback(host) {
110
+ return host === '127.0.0.1' || host === 'localhost' || host === '::1';
111
+ }
112
+ /**
113
+ * Parse a comma-separated origin allowlist string into a Set.
114
+ * Empty string returns an empty set. '*' returns a set containing '*' only.
115
+ */
116
+ export function parseOriginAllowlist(raw) {
117
+ if (!raw)
118
+ return new Set();
119
+ const origins = raw
120
+ .split(',')
121
+ .map((s) => s.trim())
122
+ .filter(Boolean);
123
+ return new Set(origins);
124
+ }
125
+ /**
126
+ * Create middleware for origin validation and CORS handling.
127
+ *
128
+ * - DNS rebinding protection: validates the Host header matches the configured
129
+ * HTTP_HOST when running on a non-loopback address.
130
+ * - Origin validation: rejects requests whose `Origin` is not in the allowlist.
131
+ * - CORS preflight: responds with appropriate headers for OPTIONS requests.
132
+ * - No-origin requests (non-browser clients) are always allowed.
133
+ */
134
+ export function createOriginValidator(config) {
135
+ const allowedOrigins = parseOriginAllowlist(config.ALLOWED_ORIGINS);
136
+ const hasExplicitAllowlist = allowedOrigins.size > 0;
137
+ const allowAll = allowedOrigins.has('*');
138
+ const loopbackMode = isLoopback(config.HTTP_HOST);
139
+ return (req, res, next) => {
140
+ // ── 1. DNS rebinding protection ───────────────────────────────────────
141
+ // On non-loopback, verify the Host header matches our configured bind address.
142
+ // This prevents an attacker from pointing a DNS name at our IP and bypassing
143
+ // browser same-origin policy.
144
+ if (!loopbackMode) {
145
+ const host = req.headers.host;
146
+ if (host) {
147
+ const expectedHost = `${config.HTTP_HOST}:${config.HTTP_PORT}`;
148
+ const expectedHostWithoutPort = config.HTTP_HOST;
149
+ if (host !== expectedHost &&
150
+ host !== expectedHostWithoutPort &&
151
+ !host.startsWith('127.0.0.1') &&
152
+ !host.startsWith('localhost')) {
153
+ res.status(400).json({
154
+ error: 'Invalid Host header',
155
+ code: 'host_mismatch',
156
+ });
157
+ return;
158
+ }
159
+ }
160
+ }
161
+ // ── 2. Origin validation ──────────────────────────────────────────────
162
+ const origin = req.headers.origin;
163
+ // Non-browser requests without an Origin header are always allowed.
164
+ if (!origin) {
57
165
  next();
58
166
  return;
59
167
  }
60
- Promise.resolve()
61
- .then(async () => {
62
- const { createRemoteJWKSet, jwtVerify } = await import('jose');
63
- if (!JWKSet) {
64
- JWKSet = createRemoteJWKSet(new URL(config.OAUTH_JWKS_URI));
168
+ // Wildcard allows everything.
169
+ if (allowAll) {
170
+ res.setHeader('Access-Control-Allow-Origin', origin);
171
+ next();
172
+ return;
173
+ }
174
+ // On loopback, accept known localhost origins and the legacy CORS_ORIGIN.
175
+ if (loopbackMode) {
176
+ const legacyMatch = config.CORS_ORIGIN && origin === config.CORS_ORIGIN;
177
+ if (LOOPBACK_ORIGINS.has(origin) || legacyMatch) {
178
+ res.setHeader('Access-Control-Allow-Origin', origin);
179
+ next();
180
+ return;
65
181
  }
66
- const { payload } = await jwtVerify(token, JWKSet, {
67
- issuer: config.OAUTH_ISSUER || undefined,
68
- audience: config.OAUTH_AUDIENCE || undefined,
69
- });
70
- res.locals.claims = payload;
182
+ }
183
+ // Check the explicit allowlist.
184
+ if (hasExplicitAllowlist && allowedOrigins.has(origin)) {
185
+ res.setHeader('Access-Control-Allow-Origin', origin);
71
186
  next();
72
- })
73
- .catch((err) => {
74
- getLogger().error({ err: err instanceof Error ? err.message : String(err) }, 'Token validation failed');
75
- res.status(403).json({ error: 'Token validation failed' });
187
+ return;
188
+ }
189
+ // ── 3. Reject unknown origins ─────────────────────────────────────────
190
+ res.status(403).json({
191
+ error: 'Origin not allowed',
192
+ code: 'origin_not_allowed',
76
193
  });
77
194
  };
78
195
  }
196
+ /** CORS preflight handler for OPTIONS requests. */
197
+ export function handleCorsPreflight(req, res, next) {
198
+ if (req.method === 'OPTIONS') {
199
+ // Vary: Origin tells caches that the response varies by the Origin header.
200
+ res.setHeader('Vary', 'Origin');
201
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
202
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
203
+ res.setHeader('Access-Control-Max-Age', '86400');
204
+ res.status(204).end();
205
+ return;
206
+ }
207
+ next();
208
+ }
79
209
  function addSecurityHeaders(_req, res, next) {
80
210
  res.setHeader('X-Content-Type-Options', 'nosniff');
81
211
  res.setHeader('X-Frame-Options', 'DENY');
82
212
  res.setHeader('X-XSS-Protection', '0');
83
213
  res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
214
+ res.setHeader('Content-Security-Policy', "default-src 'none'; frame-ancestors 'none'");
84
215
  next();
85
216
  }
86
217
  export function createHttpTransport(config) {
@@ -92,18 +223,9 @@ export function createHttpTransport(config) {
92
223
  app.use(addSecurityHeaders);
93
224
  app.use(createRateLimiter(60_000, config.HTTP_RATE_LIMIT_MAX));
94
225
  app.use(validateOAuthToken(config));
95
- if (config.CORS_ORIGIN) {
96
- app.use((req, res, next) => {
97
- res.setHeader('Access-Control-Allow-Origin', config.CORS_ORIGIN);
98
- res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
99
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
100
- if (req.method === 'OPTIONS') {
101
- res.status(204).end();
102
- return;
103
- }
104
- next();
105
- });
106
- }
226
+ // Origin validation and CORS (must come before route handlers).
227
+ app.use(createOriginValidator(config));
228
+ app.use(handleCorsPreflight);
107
229
  app.post('/mcp', (req, res) => {
108
230
  transport.handleRequest(req, res, req.body);
109
231
  });
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/server/transports/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/server/transports/http.ts"],"names":[],"mappings":"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"}
@@ -1,19 +1,44 @@
1
1
  import { type EnvConfig } from '../config/env.js';
2
2
  import { type ProjectCache, type ArtifactRecord } from './types.js';
3
+ /**
4
+ * SQLite-backed persistent storage for the MCP server.
5
+ *
6
+ * Manages project cache entries, generic key/value cache with TTL,
7
+ * and artifact records. Uses WAL mode and foreign keys for safety.
8
+ * All public methods are safe — errors are logged internally and
9
+ * never thrown to the caller.
10
+ */
3
11
  export declare class Storage {
4
12
  private db;
5
13
  private config;
6
14
  private initialized;
7
15
  constructor(config: EnvConfig);
16
+ /** Initialise the schema (tables + indexes). Safe to call multiple times. */
8
17
  initialize(): void;
18
+ /** Retrieve a cached value by key. Returns `null` when missing or expired. */
9
19
  cacheGet(key: string): string | null;
20
+ /**
21
+ * Store a value in the cache.
22
+ * @param ttlSec Time-to-live in seconds. 0 means never expire.
23
+ */
10
24
  cacheSet(key: string, value: string, ttlSec?: number): void;
25
+ /** Remove a single cache entry by key. */
11
26
  cacheDelete(key: string): void;
27
+ /** Remove all cache entries. */
12
28
  cacheClear(): void;
29
+ /** Look up a project cache entry by its hash. Returns `null` if not found. */
13
30
  getProjectCache(hash: string): ProjectCache | null;
31
+ /** Insert or replace a project cache entry. */
14
32
  upsertProjectCache(cache: ProjectCache): void;
33
+ /** Store a new artifact record (gerber, bom, pdf, etc.). */
15
34
  insertArtifact(artifact: ArtifactRecord): void;
35
+ /**
36
+ * List artifact records for a project, optionally filtered by type.
37
+ * Results are ordered by creation date descending.
38
+ */
16
39
  getArtifacts(projectHash: string, type?: string): ArtifactRecord[];
40
+ /** Reclaim storage by running VACUUM. */
17
41
  vacuum(): void;
42
+ /** Close the database connection. */
18
43
  close(): void;
19
44
  }
@@ -2,6 +2,14 @@ import { DatabaseSync } from 'node:sqlite';
2
2
  import * as path from 'node:path';
3
3
  import * as fs from 'node:fs';
4
4
  import { getLogger } from '../utils/logger.js';
5
+ /**
6
+ * SQLite-backed persistent storage for the MCP server.
7
+ *
8
+ * Manages project cache entries, generic key/value cache with TTL,
9
+ * and artifact records. Uses WAL mode and foreign keys for safety.
10
+ * All public methods are safe — errors are logged internally and
11
+ * never thrown to the caller.
12
+ */
5
13
  export class Storage {
6
14
  db;
7
15
  config;
@@ -17,6 +25,7 @@ export class Storage {
17
25
  this.db.exec('PRAGMA foreign_keys = ON');
18
26
  this.db.exec('PRAGMA busy_timeout = 5000');
19
27
  }
28
+ /** Initialise the schema (tables + indexes). Safe to call multiple times. */
20
29
  initialize() {
21
30
  if (this.initialized)
22
31
  return;
@@ -60,76 +69,142 @@ export class Storage {
60
69
  this.initialized = true;
61
70
  logger.info({ path: this.config.SQLITE_PATH }, 'storage initialized');
62
71
  }
72
+ /** Retrieve a cached value by key. Returns `null` when missing or expired. */
63
73
  cacheGet(key) {
64
- const row = this.db
65
- .prepare(`SELECT value FROM cache WHERE key = ? AND (expires_at IS NULL OR expires_at > datetime('now'))`)
66
- .get(key);
67
- return row?.value ?? null;
74
+ try {
75
+ const row = this.db
76
+ .prepare(`SELECT value FROM cache WHERE key = ? AND (expires_at IS NULL OR expires_at > datetime('now'))`)
77
+ .get(key);
78
+ return row?.value ?? null;
79
+ }
80
+ catch (err) {
81
+ getLogger().error({ err, key }, 'cacheGet failed');
82
+ return null;
83
+ }
68
84
  }
85
+ /**
86
+ * Store a value in the cache.
87
+ * @param ttlSec Time-to-live in seconds. 0 means never expire.
88
+ */
69
89
  cacheSet(key, value, ttlSec = 0) {
70
- const expiresAt = ttlSec > 0 ? new Date(Date.now() + ttlSec * 1000).toISOString() : null;
71
- this.db
72
- .prepare(`INSERT OR REPLACE INTO cache (key, value, ttl, expires_at) VALUES (?, ?, ?, ?)`)
73
- .run(key, value, ttlSec, expiresAt);
90
+ try {
91
+ const expiresAt = ttlSec > 0 ? new Date(Date.now() + ttlSec * 1000).toISOString() : null;
92
+ this.db
93
+ .prepare(`INSERT OR REPLACE INTO cache (key, value, ttl, expires_at) VALUES (?, ?, ?, ?)`)
94
+ .run(key, value, ttlSec, expiresAt);
95
+ }
96
+ catch (err) {
97
+ getLogger().error({ err, key }, 'cacheSet failed');
98
+ }
74
99
  }
100
+ /** Remove a single cache entry by key. */
75
101
  cacheDelete(key) {
76
- this.db.prepare('DELETE FROM cache WHERE key = ?').run(key);
102
+ try {
103
+ this.db.prepare('DELETE FROM cache WHERE key = ?').run(key);
104
+ }
105
+ catch (err) {
106
+ getLogger().error({ err, key }, 'cacheDelete failed');
107
+ }
77
108
  }
109
+ /** Remove all cache entries. */
78
110
  cacheClear() {
79
- this.db.prepare('DELETE FROM cache').run();
111
+ try {
112
+ this.db.prepare('DELETE FROM cache').run();
113
+ }
114
+ catch (err) {
115
+ getLogger().error({ err }, 'cacheClear failed');
116
+ }
80
117
  }
118
+ /** Look up a project cache entry by its hash. Returns `null` if not found. */
81
119
  getProjectCache(hash) {
82
- const row = this.db.prepare('SELECT * FROM project_cache WHERE project_hash = ?').get(hash);
83
- if (!row)
120
+ try {
121
+ const row = this.db
122
+ .prepare('SELECT * FROM project_cache WHERE project_hash = ?')
123
+ .get(hash);
124
+ if (!row)
125
+ return null;
126
+ return {
127
+ projectHash: row.project_hash,
128
+ projectName: row.project_name,
129
+ schematicSnapshot: row.schematic_snapshot ?? null,
130
+ boardSnapshot: row.board_snapshot ?? null,
131
+ bomSnapshot: row.bom_snapshot ?? null,
132
+ lastSyncedAt: row.last_synced_at,
133
+ easyedaVersion: row.easyeda_version ?? null,
134
+ };
135
+ }
136
+ catch (err) {
137
+ getLogger().error({ err, hash }, 'getProjectCache failed');
84
138
  return null;
85
- return {
86
- projectHash: row.project_hash,
87
- projectName: row.project_name,
88
- schematicSnapshot: row.schematic_snapshot ?? null,
89
- boardSnapshot: row.board_snapshot ?? null,
90
- bomSnapshot: row.bom_snapshot ?? null,
91
- lastSyncedAt: row.last_synced_at,
92
- easyedaVersion: row.easyeda_version ?? null,
93
- };
139
+ }
94
140
  }
141
+ /** Insert or replace a project cache entry. */
95
142
  upsertProjectCache(cache) {
96
- this.db
97
- .prepare(`
98
- INSERT OR REPLACE INTO project_cache
99
- (project_hash, project_name, schematic_snapshot, board_snapshot, bom_snapshot, last_synced_at, easyeda_version)
100
- VALUES (?, ?, ?, ?, ?, ?, ?)
101
- `)
102
- .run(cache.projectHash, cache.projectName, cache.schematicSnapshot, cache.boardSnapshot, cache.bomSnapshot, cache.lastSyncedAt, cache.easyedaVersion);
143
+ try {
144
+ this.db
145
+ .prepare(`
146
+ INSERT OR REPLACE INTO project_cache
147
+ (project_hash, project_name, schematic_snapshot, board_snapshot, bom_snapshot, last_synced_at, easyeda_version)
148
+ VALUES (?, ?, ?, ?, ?, ?, ?)
149
+ `)
150
+ .run(cache.projectHash, cache.projectName, cache.schematicSnapshot, cache.boardSnapshot, cache.bomSnapshot, cache.lastSyncedAt, cache.easyedaVersion);
151
+ }
152
+ catch (err) {
153
+ getLogger().error({ err, projectHash: cache.projectHash }, 'upsertProjectCache failed');
154
+ }
103
155
  }
156
+ /** Store a new artifact record (gerber, bom, pdf, etc.). */
104
157
  insertArtifact(artifact) {
105
- this.db
106
- .prepare(`
107
- INSERT INTO artifacts (id, project_hash, type, file_path, created_at, metadata)
108
- VALUES (?, ?, ?, ?, ?, ?)
109
- `)
110
- .run(artifact.id, artifact.projectHash, artifact.type, artifact.filePath, artifact.createdAt, artifact.metadata);
158
+ try {
159
+ this.db
160
+ .prepare(`
161
+ INSERT INTO artifacts (id, project_hash, type, file_path, created_at, metadata)
162
+ VALUES (?, ?, ?, ?, ?, ?)
163
+ `)
164
+ .run(artifact.id, artifact.projectHash, artifact.type, artifact.filePath, artifact.createdAt, artifact.metadata);
165
+ }
166
+ catch (err) {
167
+ getLogger().error({ err, artifactId: artifact.id }, 'insertArtifact failed');
168
+ }
111
169
  }
170
+ /**
171
+ * List artifact records for a project, optionally filtered by type.
172
+ * Results are ordered by creation date descending.
173
+ */
112
174
  getArtifacts(projectHash, type) {
113
- let query = 'SELECT * FROM artifacts WHERE project_hash = ?';
114
- const params = [projectHash];
115
- if (type) {
116
- query += ' AND type = ?';
117
- params.push(type);
118
- }
119
- query += ' ORDER BY created_at DESC';
120
- const rows = this.db.prepare(query).all(...params);
121
- return rows.map((r) => ({
122
- id: r.id,
123
- projectHash: r.project_hash,
124
- type: r.type,
125
- filePath: r.file_path,
126
- createdAt: r.created_at,
127
- metadata: r.metadata ?? null,
128
- }));
175
+ try {
176
+ let query = 'SELECT * FROM artifacts WHERE project_hash = ?';
177
+ const params = [projectHash];
178
+ if (type) {
179
+ query += ' AND type = ?';
180
+ params.push(type);
181
+ }
182
+ query += ' ORDER BY created_at DESC';
183
+ const rows = this.db.prepare(query).all(...params);
184
+ return rows.map((r) => ({
185
+ id: r.id,
186
+ projectHash: r.project_hash,
187
+ type: r.type,
188
+ filePath: r.file_path,
189
+ createdAt: r.created_at,
190
+ metadata: r.metadata ?? null,
191
+ }));
192
+ }
193
+ catch (err) {
194
+ getLogger().error({ err, projectHash, type }, 'getArtifacts failed');
195
+ return [];
196
+ }
129
197
  }
198
+ /** Reclaim storage by running VACUUM. */
130
199
  vacuum() {
131
- this.db.exec('VACUUM');
200
+ try {
201
+ this.db.exec('VACUUM');
202
+ }
203
+ catch (err) {
204
+ getLogger().error({ err }, 'vacuum failed');
205
+ }
132
206
  }
207
+ /** Close the database connection. */
133
208
  close() {
134
209
  this.db.close();
135
210
  }