@pinepaper.studio/mcp-server 1.6.21 → 1.6.23
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 +50 -2
- package/dist/build-info.json +2 -2
- package/dist/design/design-systems.d.ts +50 -0
- package/dist/design/design-systems.d.ts.map +1 -1
- package/dist/design/design-systems.js +220 -35
- package/dist/design/design-systems.js.map +1 -1
- package/dist/ontology/upstream-vocabulary.d.ts +1 -1
- package/dist/ontology/upstream-vocabulary.js +1 -1
- package/dist/tools/choreograph.d.ts +4 -0
- package/dist/tools/choreograph.d.ts.map +1 -1
- package/dist/tools/choreograph.js +10 -2
- package/dist/tools/choreograph.js.map +1 -1
- package/dist/tools/definitions.d.ts.map +1 -1
- package/dist/tools/definitions.js +36 -11
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/engine-lists.d.ts +2 -2
- package/dist/tools/engine-lists.js +2 -2
- package/dist/tools/engine-methods.d.ts.map +1 -1
- package/dist/tools/engine-methods.js +2 -0
- package/dist/tools/engine-methods.js.map +1 -1
- package/dist/tools/engine-surface.d.ts +1 -1
- package/dist/tools/engine-surface.d.ts.map +1 -1
- package/dist/tools/engine-surface.js +21 -6
- package/dist/tools/engine-surface.js.map +1 -1
- package/dist/tools/handlers/brand-intake.d.ts.map +1 -1
- package/dist/tools/handlers/brand-intake.js +42 -1
- package/dist/tools/handlers/brand-intake.js.map +1 -1
- package/dist/tools/handlers.d.ts +18 -1
- package/dist/tools/handlers.d.ts.map +1 -1
- package/dist/tools/handlers.js +124 -27
- package/dist/tools/handlers.js.map +1 -1
- package/dist/tools/shape-params.d.ts +2 -2
- package/dist/tools/shape-params.d.ts.map +1 -1
- package/dist/tools/shape-params.js +8 -2
- package/dist/tools/shape-params.js.map +1 -1
- package/dist/tools/stick-vocabulary.d.ts +1 -1
- package/dist/tools/stick-vocabulary.js +1 -1
- package/dist/types/code-generator.d.ts +36 -1
- package/dist/types/code-generator.d.ts.map +1 -1
- package/dist/types/code-generator.js +353 -44
- package/dist/types/code-generator.js.map +1 -1
- package/dist/types/schemas.d.ts +52 -1
- package/dist/types/schemas.d.ts.map +1 -1
- package/dist/types/schemas.js +15 -0
- package/dist/types/schemas.js.map +1 -1
- package/dist/utils/asset-paths.d.ts +11 -0
- package/dist/utils/asset-paths.d.ts.map +1 -0
- package/dist/utils/asset-paths.js +67 -0
- package/dist/utils/asset-paths.js.map +1 -0
- package/dist/utils/safe-fetch.d.ts +28 -0
- package/dist/utils/safe-fetch.d.ts.map +1 -0
- package/dist/utils/safe-fetch.js +221 -0
- package/dist/utils/safe-fetch.js.map +1 -0
- package/dist/vendor/design/bauhaus-generator.d.ts.map +1 -1
- package/dist/vendor/design/bauhaus-generator.js +20 -5
- package/dist/vendor/design/bauhaus-generator.js.map +1 -1
- package/manifest.json +1 -1
- package/package.json +6 -3
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function allowedAssetRoots(): Promise<string[]>;
|
|
2
|
+
/**
|
|
3
|
+
* The real path of `path` when it is inside an allowed folder, else an error
|
|
4
|
+
* naming the folder to add. A missing file inside the folders gets the OS reason.
|
|
5
|
+
*/
|
|
6
|
+
export declare function confineAssetPath(path: string): Promise<{
|
|
7
|
+
path: string;
|
|
8
|
+
} | {
|
|
9
|
+
error: string;
|
|
10
|
+
}>;
|
|
11
|
+
//# sourceMappingURL=asset-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-paths.d.ts","sourceRoot":"","sources":["../../src/utils/asset-paths.ts"],"names":[],"mappings":"AAwBA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAM3D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAkBlG"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keep a model-supplied local path inside the folders it may read (CWE-22).
|
|
3
|
+
*
|
|
4
|
+
* Image and media imports read a path from the user's disk and hand its bytes
|
|
5
|
+
* to the page, where they can be exported again. Unbounded, that is a way to
|
|
6
|
+
* lift any image- or media-named file off the machine the server runs on. A
|
|
7
|
+
* path is allowed only when its REAL path (symlinks resolved, so a link inside
|
|
8
|
+
* the working directory cannot point out of it) lies inside the server's
|
|
9
|
+
* working directory, its export folder, or a folder named in
|
|
10
|
+
* PINEPAPER_ASSET_DIRS (path.delimiter-separated; each entry is itself
|
|
11
|
+
* resolved).
|
|
12
|
+
*
|
|
13
|
+
* The export folder is allowed because the server's own results point into
|
|
14
|
+
* it: brand_kit from_url saves the logo there and says to import it with
|
|
15
|
+
* pinepaper_import_image. Refusing that would break the tool's own advice.
|
|
16
|
+
*/
|
|
17
|
+
import { realpath } from 'node:fs/promises';
|
|
18
|
+
import { tmpdir } from 'node:os';
|
|
19
|
+
import { basename, delimiter, dirname, join, resolve, sep } from 'node:path';
|
|
20
|
+
async function real(p) {
|
|
21
|
+
try {
|
|
22
|
+
return await realpath(p);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export async function allowedAssetRoots() {
|
|
29
|
+
// Same default as getExportDir() in handlers.ts (not imported: that module imports this one).
|
|
30
|
+
const exportDir = process.env.PINEPAPER_EXPORT_DIR || join(tmpdir(), 'pinepaper-exports');
|
|
31
|
+
const entries = [process.cwd(), exportDir, ...(process.env.PINEPAPER_ASSET_DIRS ?? '').split(delimiter).filter(Boolean)];
|
|
32
|
+
const roots = await Promise.all(entries.map((e) => real(resolve(e))));
|
|
33
|
+
return [...new Set(roots.filter((r) => r !== null))];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The real path of `path` when it is inside an allowed folder, else an error
|
|
37
|
+
* naming the folder to add. A missing file inside the folders gets the OS reason.
|
|
38
|
+
*/
|
|
39
|
+
export async function confineAssetPath(path) {
|
|
40
|
+
const roots = await allowedAssetRoots();
|
|
41
|
+
const inside = (p) => roots.some((root) => p === root || p.startsWith(root.endsWith(sep) ? root : root + sep));
|
|
42
|
+
const asked = resolve(path);
|
|
43
|
+
let target;
|
|
44
|
+
try {
|
|
45
|
+
target = await realpath(asked);
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
// A missing file outside the folders gets the same answer as a present
|
|
49
|
+
// one, so the error is not a way to probe what exists on disk. (The parent
|
|
50
|
+
// is realpath'd for the comparison: on macOS tmpdir is a /var symlink.)
|
|
51
|
+
const parent = await real(dirname(asked));
|
|
52
|
+
if (!inside(parent ? join(parent, basename(asked)) : asked))
|
|
53
|
+
return outside(path, dirname(asked));
|
|
54
|
+
const why = e instanceof Error ? e.message : 'unknown error';
|
|
55
|
+
return { error: `could not read "${path}": ${why}. Paths are resolved from the server's working directory, so pass an absolute path if in doubt.` };
|
|
56
|
+
}
|
|
57
|
+
if (inside(target))
|
|
58
|
+
return { path: target };
|
|
59
|
+
return outside(path, dirname(target));
|
|
60
|
+
}
|
|
61
|
+
function outside(path, folder) {
|
|
62
|
+
return {
|
|
63
|
+
error: `"${path}" is outside the allowed folders (cwd, the export folder, PINEPAPER_ASSET_DIRS). `
|
|
64
|
+
+ `Add its folder (${folder}) to PINEPAPER_ASSET_DIRS to import it.`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=asset-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-paths.js","sourceRoot":"","sources":["../../src/utils/asset-paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const MAX_REDIRECTS = 5;
|
|
2
|
+
export interface ResolvedAddress {
|
|
3
|
+
address: string;
|
|
4
|
+
family: 4 | 6;
|
|
5
|
+
}
|
|
6
|
+
/** Seams for tests: DNS, and the pinned transport. */
|
|
7
|
+
export declare const safeFetchDeps: {
|
|
8
|
+
lookup: (host: string) => Promise<ResolvedAddress[]>;
|
|
9
|
+
request: (url: URL, addresses: ResolvedAddress[], init: RequestInit) => Promise<Response>;
|
|
10
|
+
};
|
|
11
|
+
export declare function privateNetworkAllowed(): boolean;
|
|
12
|
+
/** 'metadata' | 'private' | null (public). */
|
|
13
|
+
export declare function classifyAddress(address: string): 'metadata' | 'private' | null;
|
|
14
|
+
export declare class UnsafeUrlError extends Error {
|
|
15
|
+
constructor(message: string);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolve a URL's host and refuse it unless every address is public.
|
|
19
|
+
* Returns the checked addresses, which the connection is then pinned to.
|
|
20
|
+
*/
|
|
21
|
+
export declare function checkUrl(input: string | URL): Promise<ResolvedAddress[]>;
|
|
22
|
+
/**
|
|
23
|
+
* fetch(), with every hop's address checked and the connection pinned to it.
|
|
24
|
+
* Redirects are followed here; `init.redirect` is ignored. The body is read
|
|
25
|
+
* in full before returning, so the per-request connection can be closed.
|
|
26
|
+
*/
|
|
27
|
+
export declare function safeFetch(input: string | URL, init?: RequestInit): Promise<Response>;
|
|
28
|
+
//# sourceMappingURL=safe-fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-fetch.d.ts","sourceRoot":"","sources":["../../src/utils/safe-fetch.ts"],"names":[],"mappings":"AAuCA,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B,MAAM,WAAW,eAAe;IAAG,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAA;CAAE;AAEnE,sDAAsD;AACtD,eAAO,MAAM,aAAa,EAAE;IAC1B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACrD,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CAI3F,CAAC;AAyBF,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AA6BD,8CAA8C;AAC9C,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAW9E;AAED,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAaD;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CA8B9E;AAKD;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAa9F"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One guarded fetch for every URL a model hands the server (CWE-918).
|
|
3
|
+
*
|
|
4
|
+
* The server fetches remote images, SVGs and media itself, because the
|
|
5
|
+
* studio page's CSP refuses a third-party fetch. That makes this process a
|
|
6
|
+
* proxy for whatever URL arrives in a tool call, and this process can reach
|
|
7
|
+
* things the model's user never meant to expose: the loopback services of the
|
|
8
|
+
* machine it runs on, the LAN, and a cloud host's metadata endpoint, which
|
|
9
|
+
* hands out credentials. So a URL is resolved here and refused when any
|
|
10
|
+
* address it resolves to is private, loopback, link-local or reserved.
|
|
11
|
+
*
|
|
12
|
+
* Three things a plain address check misses, and how each is closed:
|
|
13
|
+
* - REDIRECTS. A public URL can 302 to http://127.0.0.1/. Redirects are
|
|
14
|
+
* followed here, one hop at a time (at most MAX_REDIRECTS), and every
|
|
15
|
+
* Location is checked by the same rules before it is connected to.
|
|
16
|
+
* - DNS REBINDING. A name can resolve to a public address for the check and
|
|
17
|
+
* to 127.0.0.1 for the connection. The connection is pinned: undici's
|
|
18
|
+
* connect.lookup returns exactly the addresses that were checked, so the
|
|
19
|
+
* socket cannot go anywhere else. (Bun's undici shim ignores
|
|
20
|
+
* connect.lookup; the published bin runs under node, where it holds.
|
|
21
|
+
* Under bun this degrades to check-then-connect.)
|
|
22
|
+
* - MAPPED FORMS. ::ffff:127.0.0.1 and 64:ff9b::7f00:1 are loopback in
|
|
23
|
+
* IPv6 clothing. BlockList matches IPv4 rules against mapped addresses;
|
|
24
|
+
* the NAT64 and 6to4 prefixes are unpacked and checked as IPv4.
|
|
25
|
+
*
|
|
26
|
+
* The opt-in: PINEPAPER_ALLOW_PRIVATE_NETWORK=1 allows loopback, private and
|
|
27
|
+
* LAN addresses, for a local dev server. Cloud metadata addresses stay
|
|
28
|
+
* refused with it set: nothing a design tool does needs them.
|
|
29
|
+
*
|
|
30
|
+
* undici and node:dns are loaded lazily. This module is also bundled into a
|
|
31
|
+
* Cloudflare Worker, which has neither in the same form; there, the literal
|
|
32
|
+
* address is still checked and the platform's own fetch does the rest
|
|
33
|
+
* (Workers cannot open connections to private addresses).
|
|
34
|
+
*
|
|
35
|
+
* Keep this file to node builtins and undici, with no relative imports: the
|
|
36
|
+
* pinning test loads it in a plain node process (bun cannot exercise pinning).
|
|
37
|
+
*/
|
|
38
|
+
import { BlockList, isIP } from 'node:net';
|
|
39
|
+
export const MAX_REDIRECTS = 5;
|
|
40
|
+
/** Seams for tests: DNS, and the pinned transport. */
|
|
41
|
+
export const safeFetchDeps = {
|
|
42
|
+
lookup: defaultLookup,
|
|
43
|
+
request: pinnedRequest,
|
|
44
|
+
};
|
|
45
|
+
const PRIVATE = new BlockList();
|
|
46
|
+
for (const [net, bits] of [
|
|
47
|
+
['0.0.0.0', 8], ['10.0.0.0', 8], ['100.64.0.0', 10], ['127.0.0.0', 8],
|
|
48
|
+
['169.254.0.0', 16], ['172.16.0.0', 12], ['192.0.0.0', 24], ['192.0.2.0', 24],
|
|
49
|
+
['192.168.0.0', 16], ['198.18.0.0', 15], ['198.51.100.0', 24], ['203.0.113.0', 24],
|
|
50
|
+
['224.0.0.0', 4], ['240.0.0.0', 4],
|
|
51
|
+
])
|
|
52
|
+
PRIVATE.addSubnet(net, bits, 'ipv4');
|
|
53
|
+
for (const [net, bits] of [
|
|
54
|
+
// 64:ff9b:1::/48 is NAT64 LOCAL-USE (RFC 8215): it translates to addresses
|
|
55
|
+
// inside the operator's own network, so it is private, not unpacked.
|
|
56
|
+
['::', 96], ['64:ff9b:1::', 48], ['100::', 64], ['2001:db8::', 32], ['fc00::', 7],
|
|
57
|
+
['fe80::', 10], ['fec0::', 10], ['ff00::', 8],
|
|
58
|
+
])
|
|
59
|
+
PRIVATE.addSubnet(net, bits, 'ipv6');
|
|
60
|
+
/** Refused even with the opt-in. */
|
|
61
|
+
const METADATA = new BlockList();
|
|
62
|
+
for (const a of ['169.254.169.254', '169.254.170.2', '100.100.100.200'])
|
|
63
|
+
METADATA.addAddress(a, 'ipv4');
|
|
64
|
+
METADATA.addAddress('fd00:ec2::254', 'ipv6');
|
|
65
|
+
function env(name) {
|
|
66
|
+
return typeof process !== 'undefined' ? process.env?.[name] : undefined;
|
|
67
|
+
}
|
|
68
|
+
export function privateNetworkAllowed() {
|
|
69
|
+
return /^(1|true|yes)$/i.test(env('PINEPAPER_ALLOW_PRIVATE_NETWORK') ?? '');
|
|
70
|
+
}
|
|
71
|
+
/** The IPv4 address an IPv6 address carries, for NAT64 (64:ff9b::/96) and 6to4 (2002::/16). */
|
|
72
|
+
function embeddedIPv4(address) {
|
|
73
|
+
const groups = expandIPv6(address);
|
|
74
|
+
if (!groups)
|
|
75
|
+
return null;
|
|
76
|
+
const v4 = (hi, lo) => `${hi >> 8}.${hi & 255}.${lo >> 8}.${lo & 255}`;
|
|
77
|
+
if (groups[0] === 0x64 && groups[1] === 0xff9b && groups.slice(2, 6).every((g) => g === 0))
|
|
78
|
+
return v4(groups[6], groups[7]);
|
|
79
|
+
if (groups[0] === 0x2002)
|
|
80
|
+
return v4(groups[1], groups[2]);
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
function expandIPv6(address) {
|
|
84
|
+
let a = address.toLowerCase().split('%')[0];
|
|
85
|
+
// A trailing dotted quad (::ffff:1.2.3.4) becomes two groups.
|
|
86
|
+
const dotted = a.match(/^(.*:)(\d+\.\d+\.\d+\.\d+)$/);
|
|
87
|
+
if (dotted) {
|
|
88
|
+
const o = dotted[2].split('.').map(Number);
|
|
89
|
+
a = `${dotted[1]}${((o[0] << 8) | o[1]).toString(16)}:${((o[2] << 8) | o[3]).toString(16)}`;
|
|
90
|
+
}
|
|
91
|
+
const [head, tail] = a.includes('::') ? a.split('::') : [a, null];
|
|
92
|
+
const h = head ? head.split(':') : [];
|
|
93
|
+
const t = tail ? tail.split(':') : [];
|
|
94
|
+
const fill = tail === null ? [] : new Array(8 - h.length - t.length).fill('0');
|
|
95
|
+
const all = [...h, ...fill, ...t];
|
|
96
|
+
if (all.length !== 8)
|
|
97
|
+
return null;
|
|
98
|
+
return all.map((g) => parseInt(g, 16));
|
|
99
|
+
}
|
|
100
|
+
/** 'metadata' | 'private' | null (public). */
|
|
101
|
+
export function classifyAddress(address) {
|
|
102
|
+
const family = isIP(address);
|
|
103
|
+
if (family === 0)
|
|
104
|
+
return 'private'; // not an address at all: never connect to it
|
|
105
|
+
const type = family === 4 ? 'ipv4' : 'ipv6';
|
|
106
|
+
if (METADATA.check(address, type))
|
|
107
|
+
return 'metadata';
|
|
108
|
+
if (PRIVATE.check(address, type))
|
|
109
|
+
return 'private';
|
|
110
|
+
if (family === 6) {
|
|
111
|
+
const v4 = embeddedIPv4(address);
|
|
112
|
+
if (v4)
|
|
113
|
+
return classifyAddress(v4);
|
|
114
|
+
}
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
export class UnsafeUrlError extends Error {
|
|
118
|
+
constructor(message) {
|
|
119
|
+
super(message);
|
|
120
|
+
this.name = 'UnsafeUrlError';
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function defaultLookup(host) {
|
|
124
|
+
let dns;
|
|
125
|
+
try {
|
|
126
|
+
dns = await import('node:dns/promises');
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return []; // no resolver (a Worker): the literal check already ran
|
|
130
|
+
}
|
|
131
|
+
const all = await dns.lookup(host, { all: true, verbatim: true });
|
|
132
|
+
return all.map((r) => ({ address: r.address, family: r.family === 6 ? 6 : 4 }));
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Resolve a URL's host and refuse it unless every address is public.
|
|
136
|
+
* Returns the checked addresses, which the connection is then pinned to.
|
|
137
|
+
*/
|
|
138
|
+
export async function checkUrl(input) {
|
|
139
|
+
let url;
|
|
140
|
+
try {
|
|
141
|
+
url = typeof input === 'string' ? new URL(input) : input;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
throw new UnsafeUrlError(`refused "${String(input)}" — not a valid URL.`);
|
|
145
|
+
}
|
|
146
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
147
|
+
throw new UnsafeUrlError(`refused ${url.href} — only http and https URLs are fetched.`);
|
|
148
|
+
}
|
|
149
|
+
const host = url.hostname.replace(/^\[|\]$/g, '');
|
|
150
|
+
const literal = isIP(host);
|
|
151
|
+
let addresses;
|
|
152
|
+
if (literal) {
|
|
153
|
+
addresses = [{ address: host, family: literal === 6 ? 6 : 4 }];
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
addresses = await safeFetchDeps.lookup(host);
|
|
157
|
+
if (!addresses.length && /(^|\.)localhost$/i.test(host))
|
|
158
|
+
addresses = [{ address: '127.0.0.1', family: 4 }];
|
|
159
|
+
}
|
|
160
|
+
const allowPrivate = privateNetworkAllowed();
|
|
161
|
+
for (const { address } of addresses) {
|
|
162
|
+
const kind = classifyAddress(address);
|
|
163
|
+
if (kind === 'metadata') {
|
|
164
|
+
throw new UnsafeUrlError(`refused ${url.href} — it resolves to ${address}, a cloud metadata address. This is refused even with PINEPAPER_ALLOW_PRIVATE_NETWORK=1.`);
|
|
165
|
+
}
|
|
166
|
+
if (kind === 'private' && !allowPrivate) {
|
|
167
|
+
throw new UnsafeUrlError(`refused ${url.href} — it resolves to ${address}, a private address. Set PINEPAPER_ALLOW_PRIVATE_NETWORK=1 to allow local hosts.`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return addresses;
|
|
171
|
+
}
|
|
172
|
+
const REDIRECT = new Set([301, 302, 303, 307, 308]);
|
|
173
|
+
const NULL_BODY = new Set([101, 103, 204, 205, 304]);
|
|
174
|
+
/**
|
|
175
|
+
* fetch(), with every hop's address checked and the connection pinned to it.
|
|
176
|
+
* Redirects are followed here; `init.redirect` is ignored. The body is read
|
|
177
|
+
* in full before returning, so the per-request connection can be closed.
|
|
178
|
+
*/
|
|
179
|
+
export async function safeFetch(input, init = {}) {
|
|
180
|
+
let url = typeof input === 'string' ? new URL(input) : input;
|
|
181
|
+
for (let hop = 0;; hop++) {
|
|
182
|
+
const addresses = await checkUrl(url);
|
|
183
|
+
const res = await safeFetchDeps.request(url, addresses, { ...init, redirect: 'manual' });
|
|
184
|
+
if (!REDIRECT.has(res.status))
|
|
185
|
+
return res;
|
|
186
|
+
const location = res.headers.get('location');
|
|
187
|
+
if (!location)
|
|
188
|
+
return res;
|
|
189
|
+
if (hop >= MAX_REDIRECTS) {
|
|
190
|
+
throw new UnsafeUrlError(`refused ${input} — more than ${MAX_REDIRECTS} redirects.`);
|
|
191
|
+
}
|
|
192
|
+
url = new URL(location, url);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async function pinnedRequest(url, addresses, init) {
|
|
196
|
+
const undici = await import('undici').catch(() => null);
|
|
197
|
+
// No undici, or no resolver (a Worker): the platform fetch, which cannot
|
|
198
|
+
// reach private addresses.
|
|
199
|
+
if (!undici || !addresses.length)
|
|
200
|
+
return fetch(url, init);
|
|
201
|
+
const agent = new undici.Agent({
|
|
202
|
+
connect: {
|
|
203
|
+
lookup: (_host, opts, cb) => {
|
|
204
|
+
if (opts?.all)
|
|
205
|
+
cb(null, addresses);
|
|
206
|
+
else
|
|
207
|
+
cb(null, addresses[0].address, addresses[0].family);
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
try {
|
|
212
|
+
const res = await undici.fetch(url, { ...init, dispatcher: agent });
|
|
213
|
+
const body = NULL_BODY.has(res.status) ? null : Buffer.from(await res.arrayBuffer());
|
|
214
|
+
return new Response(body, { status: res.status, statusText: res.statusText, headers: res.headers });
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
// Bun's undici shim has no close().
|
|
218
|
+
await agent.close?.().catch(() => { });
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=safe-fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-fetch.js","sourceRoot":"","sources":["../../src/utils/safe-fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bauhaus-generator.d.ts","sourceRoot":"","sources":["../../../src/vendor/design/bauhaus-generator.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,yBAAyB,CAAC;QACtC,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;CACH;AAED,eAAO,MAAM,eAAe;;;;;;CAM3B,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,oBAAoB,GAAG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"bauhaus-generator.d.ts","sourceRoot":"","sources":["../../../src/vendor/design/bauhaus-generator.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,yBAAyB,CAAC;QACtC,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;CACH;AAED,eAAO,MAAM,eAAe;;;;;;CAM3B,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,oBAAoB,GAAG,kBAAkB,CAyIvF"}
|
|
@@ -16,14 +16,29 @@ export function generateBauhausPoster(options) {
|
|
|
16
16
|
const primaryTextColor = isDark ? BAUHAUS_PALETTE.cream : BAUHAUS_PALETTE.dark;
|
|
17
17
|
const elements = [];
|
|
18
18
|
// 1. Primary Red Circle (large architectural structural shape)
|
|
19
|
-
|
|
19
|
+
//
|
|
20
|
+
// Sized from the SHORTER side, because the text block below it is placed by the height (subtitle at
|
|
21
|
+
// 0.68 × h). Sized from the width, a 1920x1080 circle was 864 px tall and reached y = 1058, so the
|
|
22
|
+
// subtitle (734) and body ran across it; 1280x720 the same. With min(w, h) the circle ends at
|
|
23
|
+
// 0.18h + 0.45h = 0.63h on any landscape canvas, clear of the subtitle. On a portrait canvas the shorter
|
|
24
|
+
// side IS the width, so the default 1080x1350 poster is unchanged (bauhaus-landscape-layout.test.ts).
|
|
25
|
+
const circleSize = Math.round(Math.min(width, height) * 0.45);
|
|
26
|
+
// The headline is a fixed 72 px in a fixed 90 px box at 0.06h, so on a short canvas the divider (0.15h) and
|
|
27
|
+
// the circle (0.18h) would sit inside it: at 1280x720 the title box spans 43–133 and the divider was at 108,
|
|
28
|
+
// through the glyphs. The divider goes no higher than the title box's bottom, and the circle keeps its gap
|
|
29
|
+
// below the divider. Where the proportions already clear (1080x1350: divider 203, title bottom 171), both
|
|
30
|
+
// max() pick the proportional value, so the default poster is unchanged.
|
|
31
|
+
const titleY = Math.round(height * 0.06);
|
|
32
|
+
const titleHeight = 90;
|
|
33
|
+
const dividerY = Math.max(Math.round(height * 0.15), titleY + titleHeight);
|
|
34
|
+
const circleY = Math.max(Math.round(height * 0.18), dividerY + 22);
|
|
20
35
|
elements.push({
|
|
21
36
|
id: "bauhaus-red-circle",
|
|
22
37
|
type: "shape",
|
|
23
38
|
shapeType: "circle",
|
|
24
39
|
fillHex: BAUHAUS_PALETTE.red,
|
|
25
40
|
x: Math.round(width * 0.42),
|
|
26
|
-
y:
|
|
41
|
+
y: circleY,
|
|
27
42
|
width: circleSize,
|
|
28
43
|
height: circleSize,
|
|
29
44
|
hasDropShadow: false,
|
|
@@ -49,7 +64,7 @@ export function generateBauhausPoster(options) {
|
|
|
49
64
|
shapeType: "line",
|
|
50
65
|
fillHex: isDark ? BAUHAUS_PALETTE.yellow : BAUHAUS_PALETTE.dark,
|
|
51
66
|
x: Math.round(width * 0.1),
|
|
52
|
-
y:
|
|
67
|
+
y: dividerY,
|
|
53
68
|
width: Math.round(width * 0.8),
|
|
54
69
|
height: 6,
|
|
55
70
|
hasDropShadow: false,
|
|
@@ -65,9 +80,9 @@ export function generateBauhausPoster(options) {
|
|
|
65
80
|
fontFamily: "Futura, 'Bayer Universal', sans-serif",
|
|
66
81
|
fillHex: primaryTextColor,
|
|
67
82
|
x: Math.round(width * 0.1),
|
|
68
|
-
y:
|
|
83
|
+
y: titleY,
|
|
69
84
|
width: Math.round(width * 0.8),
|
|
70
|
-
height:
|
|
85
|
+
height: titleHeight,
|
|
71
86
|
textAlign: "left",
|
|
72
87
|
});
|
|
73
88
|
// 5. Subtitle Text Block
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bauhaus-generator.js","sourceRoot":"","sources":["../../../src/vendor/design/bauhaus-generator.ts"],"names":[],"mappings":"AAuDA,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,KAAK,EAAE,SAAS;IAChB,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,SAAS;CAChB,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAA6B;IACjE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC;IACpC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC;IACtC,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,IAAI,KAAK,CAAC;IAC5C,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC;IAC5E,MAAM,gBAAgB,GAAG,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC;IAE/E,MAAM,QAAQ,GAAqB,EAAE,CAAC;IAEtC,+DAA+D;IAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"bauhaus-generator.js","sourceRoot":"","sources":["../../../src/vendor/design/bauhaus-generator.ts"],"names":[],"mappings":"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"}
|
package/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pinepaper.studio/mcp-server",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.23",
|
|
4
4
|
"mcpName": "io.github.pinepaper/mcp-server",
|
|
5
5
|
"description": "MCP Server for PinePaper Studio - Create animated graphics with AI",
|
|
6
6
|
"type": "module",
|
|
@@ -83,7 +83,8 @@
|
|
|
83
83
|
"node": ">=18.0.0"
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
86
|
+
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
87
|
+
"undici": "^6",
|
|
87
88
|
"zod": "^3.22.4"
|
|
88
89
|
},
|
|
89
90
|
"devDependencies": {
|
|
@@ -114,6 +115,7 @@
|
|
|
114
115
|
],
|
|
115
116
|
"overrides": {
|
|
116
117
|
"basic-ftp": "^5.3.1",
|
|
118
|
+
"brace-expansion": "^5.0.11",
|
|
117
119
|
"body-parser": "^2.3.0",
|
|
118
120
|
"es-define-property": "npm:@socketregistry/es-define-property@^1.0.7",
|
|
119
121
|
"fast-uri": "^3.1.8",
|
|
@@ -122,10 +124,11 @@
|
|
|
122
124
|
"gopd": "npm:@socketregistry/gopd@^1.0.7",
|
|
123
125
|
"has-symbols": "npm:@socketregistry/has-symbols@^1.0.7",
|
|
124
126
|
"hasown": "npm:@socketregistry/hasown@^1.0.7",
|
|
125
|
-
"ip-address": "^10.3
|
|
127
|
+
"ip-address": "^10.7.3",
|
|
126
128
|
"js-yaml": "^4.3.1",
|
|
127
129
|
"object-assign": "npm:@socketregistry/object-assign@^1.0.5",
|
|
128
130
|
"path-to-regexp": "^8.4.2",
|
|
131
|
+
"proxy-addr": "^2.0.8",
|
|
129
132
|
"qs": "^6.16.0",
|
|
130
133
|
"safer-buffer": "npm:@socketregistry/safer-buffer@^1.0.10",
|
|
131
134
|
"side-channel": "npm:@socketregistry/side-channel@^1.0.10",
|