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.
- package/README.md +68 -24
- package/dist/bom-quality/adapter.d.ts +90 -0
- package/dist/bom-quality/adapter.js +295 -0
- package/dist/bom-quality/adapter.js.map +1 -0
- package/dist/bom-quality/index.d.ts +10 -0
- package/dist/bom-quality/index.js +9 -0
- package/dist/bom-quality/index.js.map +1 -0
- package/dist/bom-quality/quality.d.ts +28 -0
- package/dist/bom-quality/quality.js +179 -0
- package/dist/bom-quality/quality.js.map +1 -0
- package/dist/bom-quality/types.d.ts +94 -0
- package/dist/bom-quality/types.js +12 -0
- package/dist/bom-quality/types.js.map +1 -0
- package/dist/bridge/manager.d.ts +41 -0
- package/dist/bridge/manager.js +333 -51
- package/dist/bridge/manager.js.map +1 -1
- package/dist/bridge/protocol.d.ts +47 -1
- package/dist/bridge/protocol.js +42 -1
- package/dist/bridge/protocol.js.map +1 -1
- package/dist/bridge/types.d.ts +6 -0
- package/dist/bridge/types.js +6 -0
- package/dist/bridge/types.js.map +1 -1
- package/dist/catalog/errors.d.ts +49 -0
- package/dist/catalog/errors.js +60 -0
- package/dist/catalog/errors.js.map +1 -0
- package/dist/catalog/index.d.ts +15 -0
- package/dist/catalog/index.js +17 -0
- package/dist/catalog/index.js.map +1 -0
- package/dist/catalog/schema.d.ts +268 -0
- package/dist/catalog/schema.js +245 -0
- package/dist/catalog/schema.js.map +1 -0
- package/dist/catalog/starter.d.ts +159 -0
- package/dist/catalog/starter.js +579 -0
- package/dist/catalog/starter.js.map +1 -0
- package/dist/catalog/validation.d.ts +48 -0
- package/dist/catalog/validation.js +263 -0
- package/dist/catalog/validation.js.map +1 -0
- package/dist/circuit/circuit-ir.d.ts +460 -0
- package/dist/circuit/circuit-ir.js +292 -0
- package/dist/circuit/circuit-ir.js.map +1 -0
- package/dist/circuit/compiler.d.ts +55 -0
- package/dist/circuit/compiler.js +197 -0
- package/dist/circuit/compiler.js.map +1 -0
- package/dist/circuit/design-intent.d.ts +94 -0
- package/dist/circuit/design-intent.js +118 -0
- package/dist/circuit/design-intent.js.map +1 -0
- package/dist/circuit/errors.d.ts +50 -0
- package/dist/circuit/errors.js +61 -0
- package/dist/circuit/errors.js.map +1 -0
- package/dist/circuit/index.d.ts +17 -0
- package/dist/circuit/index.js +18 -0
- package/dist/circuit/index.js.map +1 -0
- package/dist/circuit/types.d.ts +186 -0
- package/dist/circuit/types.js +123 -0
- package/dist/circuit/types.js.map +1 -0
- package/dist/cli/auto-setup.d.ts +1 -8
- package/dist/cli/auto-setup.js +10 -178
- package/dist/cli/auto-setup.js.map +1 -1
- package/dist/cli/client-definitions.d.ts +34 -0
- package/dist/cli/client-definitions.js +194 -0
- package/dist/cli/client-definitions.js.map +1 -0
- package/dist/cli/local-setup.js +2 -2
- package/dist/cli/local-setup.js.map +1 -1
- package/dist/config/env.d.ts +6 -1
- package/dist/config/env.js +93 -5
- package/dist/config/env.js.map +1 -1
- package/dist/config/version.d.ts +1 -1
- package/dist/config/version.js +1 -1
- package/dist/export-manifest/errors.d.ts +55 -0
- package/dist/export-manifest/errors.js +69 -0
- package/dist/export-manifest/errors.js.map +1 -0
- package/dist/export-manifest/index.d.ts +10 -0
- package/dist/export-manifest/index.js +9 -0
- package/dist/export-manifest/index.js.map +1 -0
- package/dist/export-manifest/types.d.ts +170 -0
- package/dist/export-manifest/types.js +36 -0
- package/dist/export-manifest/types.js.map +1 -0
- package/dist/export-manifest/validation.d.ts +39 -0
- package/dist/export-manifest/validation.js +298 -0
- package/dist/export-manifest/validation.js.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/net-validation/errors.d.ts +89 -0
- package/dist/net-validation/errors.js +69 -0
- package/dist/net-validation/errors.js.map +1 -0
- package/dist/net-validation/fixtures.d.ts +38 -0
- package/dist/net-validation/fixtures.js +215 -0
- package/dist/net-validation/fixtures.js.map +1 -0
- package/dist/net-validation/index.d.ts +10 -0
- package/dist/net-validation/index.js +9 -0
- package/dist/net-validation/index.js.map +1 -0
- package/dist/net-validation/schema.d.ts +118 -0
- package/dist/net-validation/schema.js +140 -0
- package/dist/net-validation/schema.js.map +1 -0
- package/dist/net-validation/validation.d.ts +45 -0
- package/dist/net-validation/validation.js +369 -0
- package/dist/net-validation/validation.js.map +1 -0
- package/dist/pcb-constraints/errors.d.ts +39 -0
- package/dist/pcb-constraints/errors.js +133 -0
- package/dist/pcb-constraints/errors.js.map +1 -0
- package/dist/pcb-constraints/index.d.ts +9 -0
- package/dist/pcb-constraints/index.js +9 -0
- package/dist/pcb-constraints/index.js.map +1 -0
- package/dist/pcb-constraints/types.d.ts +102 -0
- package/dist/pcb-constraints/types.js +7 -0
- package/dist/pcb-constraints/types.js.map +1 -0
- package/dist/pcb-constraints/validation.d.ts +70 -0
- package/dist/pcb-constraints/validation.js +309 -0
- package/dist/pcb-constraints/validation.js.map +1 -0
- package/dist/server/factory.js +2 -0
- package/dist/server/factory.js.map +1 -1
- package/dist/server/transports/http.d.ts +20 -1
- package/dist/server/transports/http.js +156 -34
- package/dist/server/transports/http.js.map +1 -1
- package/dist/storage/database.d.ts +25 -0
- package/dist/storage/database.js +126 -51
- package/dist/storage/database.js.map +1 -1
- package/dist/tools/{L0_diagnostics.d.ts → L0_diagnostics_api.d.ts} +2 -2
- package/dist/tools/L0_diagnostics_api.js +152 -0
- package/dist/tools/L0_diagnostics_api.js.map +1 -0
- package/dist/tools/L0_diagnostics_core.d.ts +6 -0
- package/dist/tools/{L0_diagnostics.js → L0_diagnostics_core.js} +50 -124
- package/dist/tools/L0_diagnostics_core.js.map +1 -0
- package/dist/tools/L1_board.js +20 -4
- package/dist/tools/L1_board.js.map +1 -1
- package/dist/tools/{L1_bom.d.ts → L1_bom_core.d.ts} +2 -2
- package/dist/tools/{L1_bom.js → L1_bom_core.js} +21 -101
- package/dist/tools/L1_bom_core.js.map +1 -0
- package/dist/tools/{L1_schematic.d.ts → L1_bom_sourcing.d.ts} +2 -2
- package/dist/tools/L1_bom_sourcing.js +265 -0
- package/dist/tools/L1_bom_sourcing.js.map +1 -0
- package/dist/tools/L1_drc_erc.js +15 -3
- package/dist/tools/L1_drc_erc.js.map +1 -1
- package/dist/tools/L1_export.js +20 -4
- package/dist/tools/L1_export.js.map +1 -1
- package/dist/tools/L1_pcb_constraints.d.ts +6 -0
- package/dist/tools/L1_pcb_constraints.js +234 -0
- package/dist/tools/L1_pcb_constraints.js.map +1 -0
- package/dist/tools/L1_pcb_write.js +26 -12
- package/dist/tools/L1_pcb_write.js.map +1 -1
- package/dist/tools/L1_schematic_read.d.ts +6 -0
- package/dist/tools/{L1_schematic.js → L1_schematic_read.js} +125 -194
- package/dist/tools/L1_schematic_read.js.map +1 -0
- package/dist/tools/L1_schematic_write.d.ts +6 -0
- package/dist/tools/L1_schematic_write.js +516 -0
- package/dist/tools/L1_schematic_write.js.map +1 -0
- package/dist/tools/register.js +15 -7
- package/dist/tools/register.js.map +1 -1
- package/dist/tools/registry.d.ts +41 -7
- package/dist/tools/registry.js +95 -25
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/types.d.ts +16 -0
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/logger.js +1 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/vendors/base-http-client.d.ts +48 -0
- package/dist/vendors/base-http-client.js +75 -0
- package/dist/vendors/base-http-client.js.map +1 -0
- package/dist/vendors/digikey/client.js +10 -19
- package/dist/vendors/digikey/client.js.map +1 -1
- package/dist/vendors/jlcpcb/client.js +41 -70
- package/dist/vendors/jlcpcb/client.js.map +1 -1
- package/dist/vendors/lcsc/client.js +5 -18
- package/dist/vendors/lcsc/client.js.map +1 -1
- package/dist/vendors/mouser/client.js +4 -12
- package/dist/vendors/mouser/client.js.map +1 -1
- package/easyeda-bridge-extension.eext +0 -0
- package/package.json +11 -10
- package/dist/tools/L0_diagnostics.js.map +0 -1
- package/dist/tools/L1_bom.js.map +0 -1
- 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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"}
|
package/dist/server/factory.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
62
|
+
tokenError(res, 'Empty Bearer token', 'empty_token');
|
|
48
63
|
return;
|
|
49
64
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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.
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAClF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;
|
|
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
|
}
|
package/dist/storage/database.js
CHANGED
|
@@ -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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
.
|
|
73
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
83
|
-
|
|
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
|
-
|
|
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
|
-
|
|
97
|
-
.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
106
|
-
.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
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
|
}
|