@metronome/mcp 3.4.1 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/code-tool-paths.cjs +4 -2
- package/code-tool-paths.cjs.map +1 -1
- package/code-tool-paths.d.cts +1 -1
- package/code-tool-paths.d.cts.map +1 -1
- package/code-tool-worker.d.mts.map +1 -1
- package/code-tool-worker.d.ts.map +1 -1
- package/code-tool-worker.js +45 -3
- package/code-tool-worker.js.map +1 -1
- package/code-tool-worker.mjs +12 -3
- package/code-tool-worker.mjs.map +1 -1
- package/code-tool.d.mts.map +1 -1
- package/code-tool.d.ts.map +1 -1
- package/code-tool.js +31 -25
- package/code-tool.js.map +1 -1
- package/code-tool.mjs +22 -13
- package/code-tool.mjs.map +1 -1
- package/docs-search-tool.d.mts +2 -0
- package/docs-search-tool.d.mts.map +1 -1
- package/docs-search-tool.d.ts +2 -0
- package/docs-search-tool.d.ts.map +1 -1
- package/docs-search-tool.js +32 -2
- package/docs-search-tool.js.map +1 -1
- package/docs-search-tool.mjs +31 -2
- package/docs-search-tool.mjs.map +1 -1
- package/http.d.mts.map +1 -1
- package/http.d.ts.map +1 -1
- package/http.js +65 -3
- package/http.js.map +1 -1
- package/http.mjs +65 -3
- package/http.mjs.map +1 -1
- package/instructions.d.mts +4 -1
- package/instructions.d.mts.map +1 -1
- package/instructions.d.ts +4 -1
- package/instructions.d.ts.map +1 -1
- package/instructions.js +29 -14
- package/instructions.js.map +1 -1
- package/instructions.mjs +26 -14
- package/instructions.mjs.map +1 -1
- package/local-docs-search.d.mts +28 -0
- package/local-docs-search.d.mts.map +1 -0
- package/local-docs-search.d.ts +28 -0
- package/local-docs-search.d.ts.map +1 -0
- package/local-docs-search.js +4780 -0
- package/local-docs-search.js.map +1 -0
- package/local-docs-search.mjs +4740 -0
- package/local-docs-search.mjs.map +1 -0
- package/options.d.mts +3 -0
- package/options.d.mts.map +1 -1
- package/options.d.ts +3 -0
- package/options.d.ts.map +1 -1
- package/options.js +19 -0
- package/options.js.map +1 -1
- package/options.mjs +19 -0
- package/options.mjs.map +1 -1
- package/package.json +13 -2
- package/server.d.mts +10 -1
- package/server.d.mts.map +1 -1
- package/server.d.ts +10 -1
- package/server.d.ts.map +1 -1
- package/server.js +13 -3
- package/server.js.map +1 -1
- package/server.mjs +13 -3
- package/server.mjs.map +1 -1
- package/src/code-tool-paths.cts +3 -1
- package/src/code-tool-worker.ts +12 -3
- package/src/code-tool.ts +29 -18
- package/src/docs-search-tool.ts +46 -8
- package/src/http.ts +71 -3
- package/src/instructions.ts +33 -15
- package/src/local-docs-search.ts +5674 -0
- package/src/options.ts +24 -0
- package/src/server.ts +23 -3
- package/src/stdio.ts +4 -1
- package/src/types.ts +3 -0
- package/src/util.ts +2 -2
- package/stdio.d.mts.map +1 -1
- package/stdio.d.ts.map +1 -1
- package/stdio.js +4 -1
- package/stdio.js.map +1 -1
- package/stdio.mjs +4 -1
- package/stdio.mjs.map +1 -1
- package/types.d.mts +6 -0
- package/types.d.mts.map +1 -1
- package/types.d.ts +6 -0
- package/types.d.ts.map +1 -1
- package/types.js.map +1 -1
- package/types.mjs.map +1 -1
- package/util.js +2 -2
- package/util.js.map +1 -1
- package/util.mjs +2 -2
- package/util.mjs.map +1 -1
package/docs-search-tool.d.mts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
2
2
|
import { Metadata, McpRequestContext } from "./types.mjs";
|
|
3
|
+
import type { LocalDocsSearch } from "./local-docs-search.mjs";
|
|
3
4
|
export declare const metadata: Metadata;
|
|
4
5
|
export declare const tool: Tool;
|
|
6
|
+
export declare function setLocalSearch(search: LocalDocsSearch): void;
|
|
5
7
|
export declare const handler: ({ reqContext, args, }: {
|
|
6
8
|
reqContext: McpRequestContext;
|
|
7
9
|
args: Record<string, unknown> | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-search-tool.d.mts","sourceRoot":"","sources":["src/docs-search-tool.ts"],"names":[],"mappings":"OAEO,EAAE,IAAI,EAAE,MAAM,oCAAoC;OAClD,EAAE,QAAQ,EAAE,iBAAiB,EAAuB;
|
|
1
|
+
{"version":3,"file":"docs-search-tool.d.mts","sourceRoot":"","sources":["src/docs-search-tool.ts"],"names":[],"mappings":"OAEO,EAAE,IAAI,EAAE,MAAM,oCAAoC;OAClD,EAAE,QAAQ,EAAE,iBAAiB,EAAuB;OAEpD,KAAK,EAAE,eAAe,EAAE;AAE/B,eAAO,MAAM,QAAQ,EAAE,QAKtB,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,IA2BlB,CAAC;AAOF,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAE5D;AAuED,eAAO,MAAM,OAAO,GAAU,uBAG3B;IACD,UAAU,EAAE,iBAAiB,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAC3C,8CAQA,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCAXC;QACD,UAAU,EAAE,iBAAiB,CAAC;QAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;KAC3C;;AAUD,wBAA2C"}
|
package/docs-search-tool.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
2
2
|
import { Metadata, McpRequestContext } from "./types.js";
|
|
3
|
+
import type { LocalDocsSearch } from "./local-docs-search.js";
|
|
3
4
|
export declare const metadata: Metadata;
|
|
4
5
|
export declare const tool: Tool;
|
|
6
|
+
export declare function setLocalSearch(search: LocalDocsSearch): void;
|
|
5
7
|
export declare const handler: ({ reqContext, args, }: {
|
|
6
8
|
reqContext: McpRequestContext;
|
|
7
9
|
args: Record<string, unknown> | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-search-tool.d.ts","sourceRoot":"","sources":["src/docs-search-tool.ts"],"names":[],"mappings":"OAEO,EAAE,IAAI,EAAE,MAAM,oCAAoC;OAClD,EAAE,QAAQ,EAAE,iBAAiB,EAAuB;
|
|
1
|
+
{"version":3,"file":"docs-search-tool.d.ts","sourceRoot":"","sources":["src/docs-search-tool.ts"],"names":[],"mappings":"OAEO,EAAE,IAAI,EAAE,MAAM,oCAAoC;OAClD,EAAE,QAAQ,EAAE,iBAAiB,EAAuB;OAEpD,KAAK,EAAE,eAAe,EAAE;AAE/B,eAAO,MAAM,QAAQ,EAAE,QAKtB,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,IA2BlB,CAAC;AAOF,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAE5D;AAuED,eAAO,MAAM,OAAO,GAAU,uBAG3B;IACD,UAAU,EAAE,iBAAiB,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAC3C,8CAQA,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCAXC;QACD,UAAU,EAAE,iBAAiB,CAAC;QAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;KAC3C;;AAUD,wBAA2C"}
|
package/docs-search-tool.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.handler = exports.tool = exports.metadata = void 0;
|
|
5
|
+
exports.setLocalSearch = setLocalSearch;
|
|
5
6
|
const types_1 = require("./types.js");
|
|
6
7
|
const logger_1 = require("./logger.js");
|
|
7
8
|
exports.metadata = {
|
|
@@ -38,13 +39,35 @@ exports.tool = {
|
|
|
38
39
|
},
|
|
39
40
|
};
|
|
40
41
|
const docsSearchURL = process.env['DOCS_SEARCH_URL'] || 'https://api.stainless.com/api/projects/metronome/docs/search';
|
|
41
|
-
|
|
42
|
+
let _localSearch;
|
|
43
|
+
function setLocalSearch(search) {
|
|
44
|
+
_localSearch = search;
|
|
45
|
+
}
|
|
46
|
+
async function searchLocal(args) {
|
|
47
|
+
if (!_localSearch) {
|
|
48
|
+
throw new Error('Local search not initialized');
|
|
49
|
+
}
|
|
50
|
+
const query = args['query'] ?? '';
|
|
51
|
+
const language = args['language'] ?? 'typescript';
|
|
52
|
+
const detail = args['detail'] ?? 'default';
|
|
53
|
+
return _localSearch.search({
|
|
54
|
+
query,
|
|
55
|
+
language,
|
|
56
|
+
detail,
|
|
57
|
+
maxResults: 10,
|
|
58
|
+
}).results;
|
|
59
|
+
}
|
|
60
|
+
async function searchRemote(args, reqContext) {
|
|
42
61
|
const body = args;
|
|
43
62
|
const query = new URLSearchParams(body).toString();
|
|
44
63
|
const startTime = Date.now();
|
|
45
64
|
const result = await fetch(`${docsSearchURL}?${query}`, {
|
|
46
65
|
headers: {
|
|
47
66
|
...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }),
|
|
67
|
+
...(reqContext.mcpSessionId && { 'x-stainless-mcp-session-id': reqContext.mcpSessionId }),
|
|
68
|
+
...(reqContext.mcpClientInfo && {
|
|
69
|
+
'x-stainless-mcp-client-info': JSON.stringify(reqContext.mcpClientInfo),
|
|
70
|
+
}),
|
|
48
71
|
},
|
|
49
72
|
});
|
|
50
73
|
const logger = (0, logger_1.getLogger)();
|
|
@@ -67,7 +90,14 @@ const handler = async ({ reqContext, args, }) => {
|
|
|
67
90
|
durationMs: Date.now() - startTime,
|
|
68
91
|
query: body.query,
|
|
69
92
|
}, 'Got docs search result');
|
|
70
|
-
return
|
|
93
|
+
return resultBody;
|
|
94
|
+
}
|
|
95
|
+
const handler = async ({ reqContext, args, }) => {
|
|
96
|
+
const body = args ?? {};
|
|
97
|
+
if (_localSearch) {
|
|
98
|
+
return (0, types_1.asTextContentResult)(await searchLocal(body));
|
|
99
|
+
}
|
|
100
|
+
return (0, types_1.asTextContentResult)(await searchRemote(body, reqContext));
|
|
71
101
|
};
|
|
72
102
|
exports.handler = handler;
|
|
73
103
|
exports.default = { metadata: exports.metadata, tool: exports.tool, handler: exports.handler };
|
package/docs-search-tool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-search-tool.js","sourceRoot":"","sources":["src/docs-search-tool.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;
|
|
1
|
+
{"version":3,"file":"docs-search-tool.js","sourceRoot":"","sources":["src/docs-search-tool.ts"],"names":[],"mappings":"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"}
|
package/docs-search-tool.mjs
CHANGED
|
@@ -35,13 +35,35 @@ export const tool = {
|
|
|
35
35
|
},
|
|
36
36
|
};
|
|
37
37
|
const docsSearchURL = process.env['DOCS_SEARCH_URL'] || 'https://api.stainless.com/api/projects/metronome/docs/search';
|
|
38
|
-
|
|
38
|
+
let _localSearch;
|
|
39
|
+
export function setLocalSearch(search) {
|
|
40
|
+
_localSearch = search;
|
|
41
|
+
}
|
|
42
|
+
async function searchLocal(args) {
|
|
43
|
+
if (!_localSearch) {
|
|
44
|
+
throw new Error('Local search not initialized');
|
|
45
|
+
}
|
|
46
|
+
const query = args['query'] ?? '';
|
|
47
|
+
const language = args['language'] ?? 'typescript';
|
|
48
|
+
const detail = args['detail'] ?? 'default';
|
|
49
|
+
return _localSearch.search({
|
|
50
|
+
query,
|
|
51
|
+
language,
|
|
52
|
+
detail,
|
|
53
|
+
maxResults: 10,
|
|
54
|
+
}).results;
|
|
55
|
+
}
|
|
56
|
+
async function searchRemote(args, reqContext) {
|
|
39
57
|
const body = args;
|
|
40
58
|
const query = new URLSearchParams(body).toString();
|
|
41
59
|
const startTime = Date.now();
|
|
42
60
|
const result = await fetch(`${docsSearchURL}?${query}`, {
|
|
43
61
|
headers: {
|
|
44
62
|
...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }),
|
|
63
|
+
...(reqContext.mcpSessionId && { 'x-stainless-mcp-session-id': reqContext.mcpSessionId }),
|
|
64
|
+
...(reqContext.mcpClientInfo && {
|
|
65
|
+
'x-stainless-mcp-client-info': JSON.stringify(reqContext.mcpClientInfo),
|
|
66
|
+
}),
|
|
45
67
|
},
|
|
46
68
|
});
|
|
47
69
|
const logger = getLogger();
|
|
@@ -64,7 +86,14 @@ export const handler = async ({ reqContext, args, }) => {
|
|
|
64
86
|
durationMs: Date.now() - startTime,
|
|
65
87
|
query: body.query,
|
|
66
88
|
}, 'Got docs search result');
|
|
67
|
-
return
|
|
89
|
+
return resultBody;
|
|
90
|
+
}
|
|
91
|
+
export const handler = async ({ reqContext, args, }) => {
|
|
92
|
+
const body = args ?? {};
|
|
93
|
+
if (_localSearch) {
|
|
94
|
+
return asTextContentResult(await searchLocal(body));
|
|
95
|
+
}
|
|
96
|
+
return asTextContentResult(await searchRemote(body, reqContext));
|
|
68
97
|
};
|
|
69
98
|
export default { metadata, tool, handler };
|
|
70
99
|
//# sourceMappingURL=docs-search-tool.mjs.map
|
package/docs-search-tool.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-search-tool.mjs","sourceRoot":"","sources":["src/docs-search-tool.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAG/E,EAA+B,mBAAmB,EAAE;OACpD,EAAE,SAAS,EAAE;
|
|
1
|
+
{"version":3,"file":"docs-search-tool.mjs","sourceRoot":"","sources":["src/docs-search-tool.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAG/E,EAA+B,mBAAmB,EAAE;OACpD,EAAE,SAAS,EAAE;AAGpB,MAAM,CAAC,MAAM,QAAQ,GAAa;IAChC,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,MAAM;IACjB,IAAI,EAAE,EAAE;IACR,UAAU,EAAE,KAAK;CAClB,CAAC;AAEF,MAAM,CAAC,MAAM,IAAI,GAAS;IACxB,IAAI,EAAE,aAAa;IACnB,WAAW,EACT,mLAAmL;IACrL,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,0BAA0B;aACxC;YACD,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,yCAAyC;gBACtD,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC;aAClG;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,iCAAiC;gBAC9C,IAAI,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;aAC7B;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC;KAChC;IACD,WAAW,EAAE;QACX,YAAY,EAAE,IAAI;KACnB;CACF,CAAC;AAEF,MAAM,aAAa,GACjB,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,8DAA8D,CAAC;AAEnG,IAAI,YAAyC,CAAC;AAE9C,MAAM,UAAU,cAAc,CAAC,MAAuB;IACpD,YAAY,GAAG,MAAM,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,IAA6B;IACtD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,KAAK,GAAI,IAAI,CAAC,OAAO,CAAY,IAAI,EAAE,CAAC;IAC9C,MAAM,QAAQ,GAAI,IAAI,CAAC,UAAU,CAAY,IAAI,YAAY,CAAC;IAC9D,MAAM,MAAM,GAAI,IAAI,CAAC,QAAQ,CAAY,IAAI,SAAS,CAAC;IAEvD,OAAO,YAAY,CAAC,MAAM,CAAC;QACzB,KAAK;QACL,QAAQ;QACR,MAAM;QACN,UAAU,EAAE,EAAE;KACf,CAAC,CAAC,OAAO,CAAC;AACb,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAA6B,EAAE,UAA6B;IACtF,MAAM,IAAI,GAAG,IAAW,CAAC;IACzB,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEnD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,aAAa,IAAI,KAAK,EAAE,EAAE;QACtD,OAAO,EAAE;YACP,GAAG,CAAC,UAAU,CAAC,eAAe,IAAI,EAAE,aAAa,EAAE,UAAU,CAAC,eAAe,EAAE,CAAC;YAChF,GAAG,CAAC,UAAU,CAAC,YAAY,IAAI,EAAE,4BAA4B,EAAE,UAAU,CAAC,YAAY,EAAE,CAAC;YACzF,GAAG,CAAC,UAAU,CAAC,aAAa,IAAI;gBAC9B,6BAA6B,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,aAAa,CAAC;aACxE,CAAC;SACH;KACF,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,CAAC,IAAI,CACT;YACE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YAClC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,SAAS;SACV,EACD,0CAA0C,CAC3C,CAAC;QAEF,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CACb,yMAAyM,CAC1M,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,KAAK,CACb,GAAG,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,UAAU,yCAAyC,SAAS,EAAE,CAC3F,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,CAAC,IAAI,CACT;QACE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;QAClC,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,EACD,wBAAwB,CACzB,CAAC;IACF,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAAE,EAC5B,UAAU,EACV,IAAI,GAIL,EAAE,EAAE;IACH,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;IAExB,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,mBAAmB,CAAC,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,mBAAmB,CAAC,MAAM,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;AACnE,CAAC,CAAC;AAEF,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC"}
|
package/http.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.mts","sourceRoot":"","sources":["src/http.ts"],"names":[],"mappings":"OAIO,EAAE,aAAa,EAAE,MAAM,gBAAgB;OACvC,OAAO,MAAM,SAAS;OAKtB,EAAE,UAAU,EAAE;
|
|
1
|
+
{"version":3,"file":"http.d.mts","sourceRoot":"","sources":["src/http.ts"],"names":[],"mappings":"OAIO,EAAE,aAAa,EAAE,MAAM,gBAAgB;OACvC,OAAO,MAAM,SAAS;OAKtB,EAAE,UAAU,EAAE;AAgIrB,eAAO,MAAM,iBAAiB,GAAI,gCAG/B;IACD,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,EAAE,UAAU,CAAC;CACxB,KAAG,OAAO,CAAC,OA4DX,CAAC;AAEF,eAAO,MAAM,0BAA0B,GAAU,uBAG9C;IACD,UAAU,EAAE,UAAU,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC,kBAcA,CAAC"}
|
package/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["src/http.ts"],"names":[],"mappings":"OAIO,EAAE,aAAa,EAAE,MAAM,gBAAgB;OACvC,OAAO,MAAM,SAAS;OAKtB,EAAE,UAAU,EAAE;
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["src/http.ts"],"names":[],"mappings":"OAIO,EAAE,aAAa,EAAE,MAAM,gBAAgB;OACvC,OAAO,MAAM,SAAS;OAKtB,EAAE,UAAU,EAAE;AAgIrB,eAAO,MAAM,iBAAiB,GAAI,gCAG/B;IACD,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,EAAE,UAAU,CAAC;CACxB,KAAG,OAAO,CAAC,OA4DX,CAAC;AAEF,eAAO,MAAM,0BAA0B,GAAU,uBAG9C;IACD,UAAU,EAAE,UAAU,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC,kBAcA,CAAC"}
|
package/http.js
CHANGED
|
@@ -14,17 +14,65 @@ const logger_1 = require("./logger.js");
|
|
|
14
14
|
const server_1 = require("./server.js");
|
|
15
15
|
const newServer = async ({ clientOptions, mcpOptions, req, res, }) => {
|
|
16
16
|
const stainlessApiKey = (0, auth_1.getStainlessApiKey)(req, mcpOptions);
|
|
17
|
-
const
|
|
17
|
+
const customInstructionsPath = mcpOptions.customInstructionsPath;
|
|
18
|
+
const server = await (0, server_1.newMcpServer)({ stainlessApiKey, customInstructionsPath });
|
|
18
19
|
const authOptions = (0, auth_1.parseClientAuthHeaders)(req, false);
|
|
20
|
+
let upstreamClientEnvs;
|
|
21
|
+
const clientEnvsHeader = req.headers['x-stainless-mcp-client-envs'];
|
|
22
|
+
if (typeof clientEnvsHeader === 'string') {
|
|
23
|
+
try {
|
|
24
|
+
const parsed = JSON.parse(clientEnvsHeader);
|
|
25
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
26
|
+
upstreamClientEnvs = parsed;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Ignore malformed header
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Parse x-stainless-mcp-client-permissions header to override permission options
|
|
34
|
+
//
|
|
35
|
+
// Note: Permissions are best-effort and intended to prevent clients from doing unexpected things;
|
|
36
|
+
// they're not a hard security boundary, so we allow arbitrary, client-driven overrides.
|
|
37
|
+
//
|
|
38
|
+
// See the Stainless MCP documentation for more details.
|
|
39
|
+
let effectiveMcpOptions = mcpOptions;
|
|
40
|
+
const clientPermissionsHeader = req.headers['x-stainless-mcp-client-permissions'];
|
|
41
|
+
if (typeof clientPermissionsHeader === 'string') {
|
|
42
|
+
try {
|
|
43
|
+
const parsed = JSON.parse(clientPermissionsHeader);
|
|
44
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
45
|
+
effectiveMcpOptions = {
|
|
46
|
+
...mcpOptions,
|
|
47
|
+
...(typeof parsed.allow_http_gets === 'boolean' && { codeAllowHttpGets: parsed.allow_http_gets }),
|
|
48
|
+
...(Array.isArray(parsed.allowed_methods) && { codeAllowedMethods: parsed.allowed_methods }),
|
|
49
|
+
...(Array.isArray(parsed.blocked_methods) && { codeBlockedMethods: parsed.blocked_methods }),
|
|
50
|
+
};
|
|
51
|
+
(0, logger_1.getLogger)().info({ clientPermissions: parsed }, 'Overriding code execution permissions from x-stainless-mcp-client-permissions header');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
(0, logger_1.getLogger)().warn({ error }, 'Failed to parse x-stainless-mcp-client-permissions header');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const mcpClientInfo = typeof req.body?.params?.clientInfo?.name === 'string' ?
|
|
59
|
+
{ name: req.body.params.clientInfo.name, version: String(req.body.params.clientInfo.version ?? '') }
|
|
60
|
+
: undefined;
|
|
19
61
|
await (0, server_1.initMcpServer)({
|
|
20
62
|
server: server,
|
|
21
|
-
mcpOptions:
|
|
63
|
+
mcpOptions: effectiveMcpOptions,
|
|
22
64
|
clientOptions: {
|
|
23
65
|
...clientOptions,
|
|
24
66
|
...authOptions,
|
|
25
67
|
},
|
|
26
68
|
stainlessApiKey: stainlessApiKey,
|
|
69
|
+
upstreamClientEnvs,
|
|
70
|
+
mcpSessionId: req.mcpSessionId,
|
|
71
|
+
mcpClientInfo,
|
|
27
72
|
});
|
|
73
|
+
if (mcpClientInfo) {
|
|
74
|
+
(0, logger_1.getLogger)().info({ mcpSessionId: req.mcpSessionId, mcpClientInfo }, 'MCP client connected');
|
|
75
|
+
}
|
|
28
76
|
return server;
|
|
29
77
|
};
|
|
30
78
|
const post = (options) => async (req, res) => {
|
|
@@ -55,7 +103,7 @@ const del = async (req, res) => {
|
|
|
55
103
|
});
|
|
56
104
|
};
|
|
57
105
|
const redactHeaders = (headers) => {
|
|
58
|
-
const hiddenHeaders = /auth|cookie|key|token/i;
|
|
106
|
+
const hiddenHeaders = /auth|cookie|key|token|x-stainless-mcp-client-envs/i;
|
|
59
107
|
const filtered = { ...headers };
|
|
60
108
|
Object.keys(filtered).forEach((key) => {
|
|
61
109
|
if (hiddenHeaders.test(key)) {
|
|
@@ -68,8 +116,22 @@ const streamableHTTPApp = ({ clientOptions = {}, mcpOptions, }) => {
|
|
|
68
116
|
const app = (0, express_1.default)();
|
|
69
117
|
app.set('query parser', 'extended');
|
|
70
118
|
app.use(express_1.default.json());
|
|
119
|
+
app.use((req, res, next) => {
|
|
120
|
+
const existing = req.headers['mcp-session-id'];
|
|
121
|
+
const sessionId = (Array.isArray(existing) ? existing[0] : existing) || crypto.randomUUID();
|
|
122
|
+
req.mcpSessionId = sessionId;
|
|
123
|
+
const origWriteHead = res.writeHead.bind(res);
|
|
124
|
+
res.writeHead = function (statusCode, ...rest) {
|
|
125
|
+
res.setHeader('mcp-session-id', sessionId);
|
|
126
|
+
return origWriteHead(statusCode, ...rest);
|
|
127
|
+
};
|
|
128
|
+
next();
|
|
129
|
+
});
|
|
71
130
|
app.use((0, pino_http_1.default)({
|
|
72
131
|
logger: (0, logger_1.getLogger)(),
|
|
132
|
+
customProps: (req) => ({
|
|
133
|
+
mcpSessionId: req.mcpSessionId,
|
|
134
|
+
}),
|
|
73
135
|
customLogLevel: (req, res) => {
|
|
74
136
|
if (res.statusCode >= 500) {
|
|
75
137
|
return 'error';
|
package/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["src/http.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;;;;AAGtF,0FAAmG;AAEnG,sDAA8B;AAC9B,gDAAwB;AACxB,0DAAiC;AACjC,oCAAoE;AACpE,wCAAqC;AAErC,wCAAuD;AAEvD,MAAM,SAAS,GAAG,KAAK,EAAE,EACvB,aAAa,EACb,UAAU,EACV,GAAG,EACH,GAAG,GAMJ,EAA6B,EAAE;IAC9B,MAAM,eAAe,GAAG,IAAA,yBAAkB,EAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAY,EAAC,eAAe,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["src/http.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;;;;AAGtF,0FAAmG;AAEnG,sDAA8B;AAC9B,gDAAwB;AACxB,0DAAiC;AACjC,oCAAoE;AACpE,wCAAqC;AAErC,wCAAuD;AAEvD,MAAM,SAAS,GAAG,KAAK,EAAE,EACvB,aAAa,EACb,UAAU,EACV,GAAG,EACH,GAAG,GAMJ,EAA6B,EAAE;IAC9B,MAAM,eAAe,GAAG,IAAA,yBAAkB,EAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC5D,MAAM,sBAAsB,GAAG,UAAU,CAAC,sBAAsB,CAAC;IACjE,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAY,EAAC,EAAE,eAAe,EAAE,sBAAsB,EAAE,CAAC,CAAC;IAE/E,MAAM,WAAW,GAAG,IAAA,6BAAsB,EAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAEvD,IAAI,kBAAsD,CAAC;IAC3D,MAAM,gBAAgB,GAAG,GAAG,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;IACpE,IAAI,OAAO,gBAAgB,KAAK,QAAQ,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAC5C,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnE,kBAAkB,GAAG,MAAM,CAAC;YAC9B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,0BAA0B;QAC5B,CAAC;IACH,CAAC;IAED,iFAAiF;IACjF,EAAE;IACF,kGAAkG;IAClG,wFAAwF;IACxF,EAAE;IACF,wDAAwD;IACxD,IAAI,mBAAmB,GAAG,UAAU,CAAC;IACrC,MAAM,uBAAuB,GAAG,GAAG,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC;IAClF,IAAI,OAAO,uBAAuB,KAAK,QAAQ,EAAE,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;YACnD,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnE,mBAAmB,GAAG;oBACpB,GAAG,UAAU;oBACb,GAAG,CAAC,OAAO,MAAM,CAAC,eAAe,KAAK,SAAS,IAAI,EAAE,iBAAiB,EAAE,MAAM,CAAC,eAAe,EAAE,CAAC;oBACjG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,kBAAkB,EAAE,MAAM,CAAC,eAAe,EAAE,CAAC;oBAC5F,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,kBAAkB,EAAE,MAAM,CAAC,eAAe,EAAE,CAAC;iBAC7F,CAAC;gBACF,IAAA,kBAAS,GAAE,CAAC,IAAI,CACd,EAAE,iBAAiB,EAAE,MAAM,EAAE,EAC7B,sFAAsF,CACvF,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAA,kBAAS,GAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,2DAA2D,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GACjB,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC;QACtD,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE;QACtG,CAAC,CAAC,SAAS,CAAC;IAEd,MAAM,IAAA,sBAAa,EAAC;QAClB,MAAM,EAAE,MAAM;QACd,UAAU,EAAE,mBAAmB;QAC/B,aAAa,EAAE;YACb,GAAG,aAAa;YAChB,GAAG,WAAW;SACf;QACD,eAAe,EAAE,eAAe;QAChC,kBAAkB;QAClB,YAAY,EAAG,GAAW,CAAC,YAAY;QACvC,aAAa;KACd,CAAC,CAAC;IAEH,IAAI,aAAa,EAAE,CAAC;QAClB,IAAA,kBAAS,GAAE,CAAC,IAAI,CAAC,EAAE,YAAY,EAAG,GAAW,CAAC,YAAY,EAAE,aAAa,EAAE,EAAE,sBAAsB,CAAC,CAAC;IACvG,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,IAAI,GACR,CAAC,OAAiE,EAAE,EAAE,CACtE,KAAK,EAAE,GAAoB,EAAE,GAAqB,EAAE,EAAE;IACpD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IACzD,6DAA6D;IAC7D,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO;IAC5B,MAAM,SAAS,GAAG,IAAI,iDAA6B,EAAE,CAAC;IACtD,MAAM,MAAM,CAAC,OAAO,CAAC,SAAgB,CAAC,CAAC;IACvC,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC,CAAC;AAEJ,MAAM,GAAG,GAAG,KAAK,EAAE,GAAoB,EAAE,GAAqB,EAAE,EAAE;IAChE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,OAAO,EAAE,KAAK;QACd,KAAK,EAAE;YACL,IAAI,EAAE,CAAC,KAAK;YACZ,OAAO,EAAE,sBAAsB;SAChC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,GAAG,GAAG,KAAK,EAAE,GAAoB,EAAE,GAAqB,EAAE,EAAE;IAChE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,OAAO,EAAE,KAAK;QACd,KAAK,EAAE;YACL,IAAI,EAAE,CAAC,KAAK;YACZ,OAAO,EAAE,sBAAsB;SAChC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,OAA4B,EAAE,EAAE;IACrD,MAAM,aAAa,GAAG,oDAAoD,CAAC;IAC3E,MAAM,QAAQ,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;IAChC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACpC,IAAI,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,QAAQ,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;QAC/B,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEK,MAAM,iBAAiB,GAAG,CAAC,EAChC,aAAa,GAAG,EAAE,EAClB,UAAU,GAIX,EAAmB,EAAE;IACpB,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;IACtB,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IACpC,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACxB,GAAG,CAAC,GAAG,CAAC,CAAC,GAAoB,EAAE,GAAqB,EAAE,IAA0B,EAAE,EAAE;QAClF,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC/C,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAC3F,GAAW,CAAC,YAAY,GAAG,SAAS,CAAC;QACtC,MAAM,aAAa,GAAG,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9C,GAAG,CAAC,SAAS,GAAG,UAAU,UAAkB,EAAE,GAAG,IAAW;YAC1D,GAAG,CAAC,SAAS,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;YAC3C,OAAO,aAAa,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;QAC5C,CAAyB,CAAC;QAC1B,IAAI,EAAE,CAAC;IACT,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CACL,IAAA,mBAAQ,EAAC;QACP,MAAM,EAAE,IAAA,kBAAS,GAAE;QACnB,WAAW,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACrB,YAAY,EAAG,GAAW,CAAC,YAAY;SACxC,CAAC;QACF,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC3B,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;gBAC1B,OAAO,OAAO,CAAC;YACjB,CAAC;iBAAM,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;gBACjC,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,oBAAoB,EAAE,UAAU,GAAG,EAAE,GAAG;YACtC,OAAO,WAAW,GAAG,CAAC,MAAM,OAAO,GAAG,CAAC,GAAG,0BAA0B,GAAG,CAAC,UAAU,EAAE,CAAC;QACvF,CAAC;QACD,kBAAkB,EAAE,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG;YACzC,OAAO,WAAW,GAAG,CAAC,MAAM,OAAO,GAAG,CAAC,GAAG,wBAAwB,GAAG,CAAC,UAAU,EAAE,CAAC;QACrF,CAAC;QACD,WAAW,EAAE;YACX,GAAG,EAAE,cAAI,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAC,GAAG,EAAE,EAAE;gBACrD,OAAO;oBACL,GAAG,GAAG;oBACN,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC;iBACxC,CAAC;YACJ,CAAC,CAAC;YACF,GAAG,EAAE,cAAI,CAAC,cAAc,CAAC,sBAAsB,CAAC,CAAC,GAAG,EAAE,EAAE;gBACtD,OAAO;oBACL,GAAG,GAAG;oBACN,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC;iBACpC,CAAC;YACJ,CAAC,CAAC;SACH;KACF,CAAC,CACH,CAAC;IAEF,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,GAAoB,EAAE,GAAqB,EAAE,EAAE;QACvE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAClB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;IACnD,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAErB,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAlEW,QAAA,iBAAiB,qBAkE5B;AAEK,MAAM,0BAA0B,GAAG,KAAK,EAAE,EAC/C,UAAU,EACV,IAAI,GAIL,EAAE,EAAE;IACH,MAAM,GAAG,GAAG,IAAA,yBAAiB,EAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;IAEjC,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;IAE3B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,4CAA4C,OAAO,EAAE,CAAC,CAAC;IACrE,CAAC;SAAM,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,iDAAiD,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/E,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,iDAAiD,IAAI,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC,CAAC;AApBW,QAAA,0BAA0B,8BAoBrC"}
|
package/http.mjs
CHANGED
|
@@ -8,17 +8,65 @@ import { getLogger } from "./logger.mjs";
|
|
|
8
8
|
import { initMcpServer, newMcpServer } from "./server.mjs";
|
|
9
9
|
const newServer = async ({ clientOptions, mcpOptions, req, res, }) => {
|
|
10
10
|
const stainlessApiKey = getStainlessApiKey(req, mcpOptions);
|
|
11
|
-
const
|
|
11
|
+
const customInstructionsPath = mcpOptions.customInstructionsPath;
|
|
12
|
+
const server = await newMcpServer({ stainlessApiKey, customInstructionsPath });
|
|
12
13
|
const authOptions = parseClientAuthHeaders(req, false);
|
|
14
|
+
let upstreamClientEnvs;
|
|
15
|
+
const clientEnvsHeader = req.headers['x-stainless-mcp-client-envs'];
|
|
16
|
+
if (typeof clientEnvsHeader === 'string') {
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(clientEnvsHeader);
|
|
19
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
20
|
+
upstreamClientEnvs = parsed;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Ignore malformed header
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Parse x-stainless-mcp-client-permissions header to override permission options
|
|
28
|
+
//
|
|
29
|
+
// Note: Permissions are best-effort and intended to prevent clients from doing unexpected things;
|
|
30
|
+
// they're not a hard security boundary, so we allow arbitrary, client-driven overrides.
|
|
31
|
+
//
|
|
32
|
+
// See the Stainless MCP documentation for more details.
|
|
33
|
+
let effectiveMcpOptions = mcpOptions;
|
|
34
|
+
const clientPermissionsHeader = req.headers['x-stainless-mcp-client-permissions'];
|
|
35
|
+
if (typeof clientPermissionsHeader === 'string') {
|
|
36
|
+
try {
|
|
37
|
+
const parsed = JSON.parse(clientPermissionsHeader);
|
|
38
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
39
|
+
effectiveMcpOptions = {
|
|
40
|
+
...mcpOptions,
|
|
41
|
+
...(typeof parsed.allow_http_gets === 'boolean' && { codeAllowHttpGets: parsed.allow_http_gets }),
|
|
42
|
+
...(Array.isArray(parsed.allowed_methods) && { codeAllowedMethods: parsed.allowed_methods }),
|
|
43
|
+
...(Array.isArray(parsed.blocked_methods) && { codeBlockedMethods: parsed.blocked_methods }),
|
|
44
|
+
};
|
|
45
|
+
getLogger().info({ clientPermissions: parsed }, 'Overriding code execution permissions from x-stainless-mcp-client-permissions header');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
getLogger().warn({ error }, 'Failed to parse x-stainless-mcp-client-permissions header');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const mcpClientInfo = typeof req.body?.params?.clientInfo?.name === 'string' ?
|
|
53
|
+
{ name: req.body.params.clientInfo.name, version: String(req.body.params.clientInfo.version ?? '') }
|
|
54
|
+
: undefined;
|
|
13
55
|
await initMcpServer({
|
|
14
56
|
server: server,
|
|
15
|
-
mcpOptions:
|
|
57
|
+
mcpOptions: effectiveMcpOptions,
|
|
16
58
|
clientOptions: {
|
|
17
59
|
...clientOptions,
|
|
18
60
|
...authOptions,
|
|
19
61
|
},
|
|
20
62
|
stainlessApiKey: stainlessApiKey,
|
|
63
|
+
upstreamClientEnvs,
|
|
64
|
+
mcpSessionId: req.mcpSessionId,
|
|
65
|
+
mcpClientInfo,
|
|
21
66
|
});
|
|
67
|
+
if (mcpClientInfo) {
|
|
68
|
+
getLogger().info({ mcpSessionId: req.mcpSessionId, mcpClientInfo }, 'MCP client connected');
|
|
69
|
+
}
|
|
22
70
|
return server;
|
|
23
71
|
};
|
|
24
72
|
const post = (options) => async (req, res) => {
|
|
@@ -49,7 +97,7 @@ const del = async (req, res) => {
|
|
|
49
97
|
});
|
|
50
98
|
};
|
|
51
99
|
const redactHeaders = (headers) => {
|
|
52
|
-
const hiddenHeaders = /auth|cookie|key|token/i;
|
|
100
|
+
const hiddenHeaders = /auth|cookie|key|token|x-stainless-mcp-client-envs/i;
|
|
53
101
|
const filtered = { ...headers };
|
|
54
102
|
Object.keys(filtered).forEach((key) => {
|
|
55
103
|
if (hiddenHeaders.test(key)) {
|
|
@@ -62,8 +110,22 @@ export const streamableHTTPApp = ({ clientOptions = {}, mcpOptions, }) => {
|
|
|
62
110
|
const app = express();
|
|
63
111
|
app.set('query parser', 'extended');
|
|
64
112
|
app.use(express.json());
|
|
113
|
+
app.use((req, res, next) => {
|
|
114
|
+
const existing = req.headers['mcp-session-id'];
|
|
115
|
+
const sessionId = (Array.isArray(existing) ? existing[0] : existing) || crypto.randomUUID();
|
|
116
|
+
req.mcpSessionId = sessionId;
|
|
117
|
+
const origWriteHead = res.writeHead.bind(res);
|
|
118
|
+
res.writeHead = function (statusCode, ...rest) {
|
|
119
|
+
res.setHeader('mcp-session-id', sessionId);
|
|
120
|
+
return origWriteHead(statusCode, ...rest);
|
|
121
|
+
};
|
|
122
|
+
next();
|
|
123
|
+
});
|
|
65
124
|
app.use(pinoHttp({
|
|
66
125
|
logger: getLogger(),
|
|
126
|
+
customProps: (req) => ({
|
|
127
|
+
mcpSessionId: req.mcpSessionId,
|
|
128
|
+
}),
|
|
67
129
|
customLogLevel: (req, res) => {
|
|
68
130
|
if (res.statusCode >= 500) {
|
|
69
131
|
return 'error';
|
package/http.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.mjs","sourceRoot":"","sources":["src/http.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAG/E,EAAE,6BAA6B,EAAE,MAAM,oDAAoD;OAE3F,OAAO,MAAM,SAAS;OACtB,IAAI,MAAM,MAAM;OAChB,QAAQ,MAAM,WAAW;OACzB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE;OAC9C,EAAE,SAAS,EAAE;OAEb,EAAE,aAAa,EAAE,YAAY,EAAE;AAEtC,MAAM,SAAS,GAAG,KAAK,EAAE,EACvB,aAAa,EACb,UAAU,EACV,GAAG,EACH,GAAG,GAMJ,EAA6B,EAAE;IAC9B,MAAM,eAAe,GAAG,kBAAkB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,eAAe,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"http.mjs","sourceRoot":"","sources":["src/http.ts"],"names":[],"mappings":"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"}
|
package/instructions.d.mts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
export declare function getInstructions(stainlessApiKey
|
|
1
|
+
export declare function getInstructions({ stainlessApiKey, customInstructionsPath, }: {
|
|
2
|
+
stainlessApiKey?: string | undefined;
|
|
3
|
+
customInstructionsPath?: string | undefined;
|
|
4
|
+
}): Promise<string>;
|
|
2
5
|
//# sourceMappingURL=instructions.d.mts.map
|
package/instructions.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.d.mts","sourceRoot":"","sources":["src/instructions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"instructions.d.mts","sourceRoot":"","sources":["src/instructions.ts"],"names":[],"mappings":"AAeA,wBAAsB,eAAe,CAAC,EACpC,eAAe,EACf,sBAAsB,GACvB,EAAE;IACD,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,sBAAsB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7C,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BlB"}
|
package/instructions.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
export declare function getInstructions(stainlessApiKey
|
|
1
|
+
export declare function getInstructions({ stainlessApiKey, customInstructionsPath, }: {
|
|
2
|
+
stainlessApiKey?: string | undefined;
|
|
3
|
+
customInstructionsPath?: string | undefined;
|
|
4
|
+
}): Promise<string>;
|
|
2
5
|
//# sourceMappingURL=instructions.d.ts.map
|
package/instructions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["src/instructions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["src/instructions.ts"],"names":[],"mappings":"AAeA,wBAAsB,eAAe,CAAC,EACpC,eAAe,EACf,sBAAsB,GACvB,EAAE;IACD,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,sBAAsB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7C,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BlB"}
|
package/instructions.js
CHANGED
|
@@ -1,33 +1,48 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
3
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
7
|
exports.getInstructions = getInstructions;
|
|
5
|
-
const
|
|
8
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
6
9
|
const logger_1 = require("./logger.js");
|
|
10
|
+
const util_1 = require("./util.js");
|
|
7
11
|
const INSTRUCTIONS_CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes
|
|
8
12
|
const instructionsCache = new Map();
|
|
9
|
-
|
|
10
|
-
const _cacheCleanupInterval = setInterval(() => {
|
|
13
|
+
async function getInstructions({ stainlessApiKey, customInstructionsPath, }) {
|
|
11
14
|
const now = Date.now();
|
|
15
|
+
const cacheKey = customInstructionsPath ?? stainlessApiKey ?? '';
|
|
16
|
+
const cached = instructionsCache.get(cacheKey);
|
|
17
|
+
if (cached && now - cached.fetchedAt <= INSTRUCTIONS_CACHE_TTL_MS) {
|
|
18
|
+
return cached.fetchedInstructions;
|
|
19
|
+
}
|
|
20
|
+
// Evict stale entries so the cache doesn't grow unboundedly.
|
|
12
21
|
for (const [key, entry] of instructionsCache) {
|
|
13
22
|
if (now - entry.fetchedAt > INSTRUCTIONS_CACHE_TTL_MS) {
|
|
14
23
|
instructionsCache.delete(key);
|
|
15
24
|
}
|
|
16
25
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (cached && Date.now() - cached.fetchedAt <= INSTRUCTIONS_CACHE_TTL_MS) {
|
|
24
|
-
return cached.fetchedInstructions;
|
|
26
|
+
let fetchedInstructions;
|
|
27
|
+
if (customInstructionsPath) {
|
|
28
|
+
fetchedInstructions = await fetchLatestInstructionsFromFile(customInstructionsPath);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
fetchedInstructions = await fetchLatestInstructionsFromApi(stainlessApiKey);
|
|
25
32
|
}
|
|
26
|
-
|
|
27
|
-
instructionsCache.set(cacheKey, { fetchedInstructions, fetchedAt: Date.now() });
|
|
33
|
+
instructionsCache.set(cacheKey, { fetchedInstructions, fetchedAt: now });
|
|
28
34
|
return fetchedInstructions;
|
|
29
35
|
}
|
|
30
|
-
async function
|
|
36
|
+
async function fetchLatestInstructionsFromFile(path) {
|
|
37
|
+
try {
|
|
38
|
+
return await promises_1.default.readFile(path, 'utf-8');
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
(0, logger_1.getLogger)().error({ error, path }, 'Error fetching instructions from file');
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function fetchLatestInstructionsFromApi(stainlessApiKey) {
|
|
31
46
|
// Setting the stainless API key is optional, but may be required
|
|
32
47
|
// to authenticate requests to the Stainless API.
|
|
33
48
|
const response = await fetch((0, util_1.readEnv)('CODE_MODE_INSTRUCTIONS_URL') ?? 'https://api.stainless.com/api/ai/instructions/metronome', {
|
package/instructions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["src/instructions.ts"],"names":[],"mappings":";AAAA,sFAAsF
|
|
1
|
+
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["src/instructions.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;;;AAetF,0CAgCC;AA7CD,2DAA6B;AAC7B,wCAAqC;AACrC,oCAAiC;AAEjC,MAAM,yBAAyB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAO/D,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAkC,CAAC;AAE7D,KAAK,UAAU,eAAe,CAAC,EACpC,eAAe,EACf,sBAAsB,GAIvB;IACC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,sBAAsB,IAAI,eAAe,IAAI,EAAE,CAAC;IACjE,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAE/C,IAAI,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,yBAAyB,EAAE,CAAC;QAClE,OAAO,MAAM,CAAC,mBAAmB,CAAC;IACpC,CAAC;IAED,6DAA6D;IAC7D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,iBAAiB,EAAE,CAAC;QAC7C,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,GAAG,yBAAyB,EAAE,CAAC;YACtD,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,IAAI,mBAA2B,CAAC;IAEhC,IAAI,sBAAsB,EAAE,CAAC;QAC3B,mBAAmB,GAAG,MAAM,+BAA+B,CAAC,sBAAsB,CAAC,CAAC;IACtF,CAAC;SAAM,CAAC;QACN,mBAAmB,GAAG,MAAM,8BAA8B,CAAC,eAAe,CAAC,CAAC;IAC9E,CAAC;IAED,iBAAiB,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,mBAAmB,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;IACzE,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED,KAAK,UAAU,+BAA+B,CAAC,IAAY;IACzD,IAAI,CAAC;QACH,OAAO,MAAM,kBAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAA,kBAAS,GAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,uCAAuC,CAAC,CAAC;QAC5E,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,8BAA8B,CAAC,eAAmC;IAC/E,iEAAiE;IACjE,iDAAiD;IACjD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,IAAA,cAAO,EAAC,4BAA4B,CAAC,IAAI,yDAAyD,EAClG;QACE,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,EAAE,GAAG,CAAC,eAAe,IAAI,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC,EAAE;KACxE,CACF,CAAC;IAEF,IAAI,YAAgC,CAAC;IACrC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAA,kBAAS,GAAE,CAAC,IAAI,CACd,8FAA8F,CAC/F,CAAC;QAEF,YAAY;YACV,07BAA07B,CAAC;IAC/7B,CAAC;IAED,YAAY,KAAM,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA8B,CAAC,YAAY,CAAC;IAEpF,OAAO,YAAY,CAAC;AACtB,CAAC"}
|
package/instructions.mjs
CHANGED
|
@@ -1,30 +1,42 @@
|
|
|
1
1
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
2
|
-
import
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
3
|
import { getLogger } from "./logger.mjs";
|
|
4
|
+
import { readEnv } from "./util.mjs";
|
|
4
5
|
const INSTRUCTIONS_CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes
|
|
5
6
|
const instructionsCache = new Map();
|
|
6
|
-
|
|
7
|
-
const _cacheCleanupInterval = setInterval(() => {
|
|
7
|
+
export async function getInstructions({ stainlessApiKey, customInstructionsPath, }) {
|
|
8
8
|
const now = Date.now();
|
|
9
|
+
const cacheKey = customInstructionsPath ?? stainlessApiKey ?? '';
|
|
10
|
+
const cached = instructionsCache.get(cacheKey);
|
|
11
|
+
if (cached && now - cached.fetchedAt <= INSTRUCTIONS_CACHE_TTL_MS) {
|
|
12
|
+
return cached.fetchedInstructions;
|
|
13
|
+
}
|
|
14
|
+
// Evict stale entries so the cache doesn't grow unboundedly.
|
|
9
15
|
for (const [key, entry] of instructionsCache) {
|
|
10
16
|
if (now - entry.fetchedAt > INSTRUCTIONS_CACHE_TTL_MS) {
|
|
11
17
|
instructionsCache.delete(key);
|
|
12
18
|
}
|
|
13
19
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (cached && Date.now() - cached.fetchedAt <= INSTRUCTIONS_CACHE_TTL_MS) {
|
|
21
|
-
return cached.fetchedInstructions;
|
|
20
|
+
let fetchedInstructions;
|
|
21
|
+
if (customInstructionsPath) {
|
|
22
|
+
fetchedInstructions = await fetchLatestInstructionsFromFile(customInstructionsPath);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
fetchedInstructions = await fetchLatestInstructionsFromApi(stainlessApiKey);
|
|
22
26
|
}
|
|
23
|
-
|
|
24
|
-
instructionsCache.set(cacheKey, { fetchedInstructions, fetchedAt: Date.now() });
|
|
27
|
+
instructionsCache.set(cacheKey, { fetchedInstructions, fetchedAt: now });
|
|
25
28
|
return fetchedInstructions;
|
|
26
29
|
}
|
|
27
|
-
async function
|
|
30
|
+
async function fetchLatestInstructionsFromFile(path) {
|
|
31
|
+
try {
|
|
32
|
+
return await fs.readFile(path, 'utf-8');
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
getLogger().error({ error, path }, 'Error fetching instructions from file');
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function fetchLatestInstructionsFromApi(stainlessApiKey) {
|
|
28
40
|
// Setting the stainless API key is optional, but may be required
|
|
29
41
|
// to authenticate requests to the Stainless API.
|
|
30
42
|
const response = await fetch(readEnv('CODE_MODE_INSTRUCTIONS_URL') ?? 'https://api.stainless.com/api/ai/instructions/metronome', {
|
package/instructions.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.mjs","sourceRoot":"","sources":["src/instructions.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAE/E,EAAE,
|
|
1
|
+
{"version":3,"file":"instructions.mjs","sourceRoot":"","sources":["src/instructions.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAE/E,EAAE,MAAM,aAAa;OACrB,EAAE,SAAS,EAAE;OACb,EAAE,OAAO,EAAE;AAElB,MAAM,yBAAyB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAO/D,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAkC,CAAC;AAEpE,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EACpC,eAAe,EACf,sBAAsB,GAIvB;IACC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,sBAAsB,IAAI,eAAe,IAAI,EAAE,CAAC;IACjE,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAE/C,IAAI,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,yBAAyB,EAAE,CAAC;QAClE,OAAO,MAAM,CAAC,mBAAmB,CAAC;IACpC,CAAC;IAED,6DAA6D;IAC7D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,iBAAiB,EAAE,CAAC;QAC7C,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,GAAG,yBAAyB,EAAE,CAAC;YACtD,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,IAAI,mBAA2B,CAAC;IAEhC,IAAI,sBAAsB,EAAE,CAAC;QAC3B,mBAAmB,GAAG,MAAM,+BAA+B,CAAC,sBAAsB,CAAC,CAAC;IACtF,CAAC;SAAM,CAAC;QACN,mBAAmB,GAAG,MAAM,8BAA8B,CAAC,eAAe,CAAC,CAAC;IAC9E,CAAC;IAED,iBAAiB,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,mBAAmB,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;IACzE,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED,KAAK,UAAU,+BAA+B,CAAC,IAAY;IACzD,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,SAAS,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,uCAAuC,CAAC,CAAC;QAC5E,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,8BAA8B,CAAC,eAAmC;IAC/E,iEAAiE;IACjE,iDAAiD;IACjD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,OAAO,CAAC,4BAA4B,CAAC,IAAI,yDAAyD,EAClG;QACE,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,EAAE,GAAG,CAAC,eAAe,IAAI,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC,EAAE;KACxE,CACF,CAAC;IAEF,IAAI,YAAgC,CAAC;IACrC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,SAAS,EAAE,CAAC,IAAI,CACd,8FAA8F,CAC/F,CAAC;QAEF,YAAY;YACV,07BAA07B,CAAC;IAC/7B,CAAC;IAED,YAAY,KAAM,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA8B,CAAC,YAAY,CAAC;IAEpF,OAAO,YAAY,CAAC;AACtB,CAAC"}
|