@studiometa/productive-mcp 0.10.8 → 0.10.9
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/dist/errors.d.ts.map +1 -1
- package/dist/handlers/activities.d.ts +98 -3
- package/dist/handlers/activities.d.ts.map +1 -1
- package/dist/handlers/attachments.d.ts +98 -3
- package/dist/handlers/attachments.d.ts.map +1 -1
- package/dist/handlers/bookings.d.ts +98 -3
- package/dist/handlers/bookings.d.ts.map +1 -1
- package/dist/handlers/comments.d.ts +98 -3
- package/dist/handlers/comments.d.ts.map +1 -1
- package/dist/handlers/companies.d.ts +98 -3
- package/dist/handlers/companies.d.ts.map +1 -1
- package/dist/handlers/custom-fields.d.ts +98 -3
- package/dist/handlers/custom-fields.d.ts.map +1 -1
- package/dist/handlers/deals.d.ts +98 -3
- package/dist/handlers/deals.d.ts.map +1 -1
- package/dist/handlers/discussions.d.ts +98 -3
- package/dist/handlers/discussions.d.ts.map +1 -1
- package/dist/handlers/pages.d.ts +98 -3
- package/dist/handlers/pages.d.ts.map +1 -1
- package/dist/handlers/projects.d.ts +98 -3
- package/dist/handlers/projects.d.ts.map +1 -1
- package/dist/handlers/services.d.ts +98 -3
- package/dist/handlers/services.d.ts.map +1 -1
- package/dist/handlers/tasks.d.ts +98 -3
- package/dist/handlers/tasks.d.ts.map +1 -1
- package/dist/handlers/time.d.ts +98 -3
- package/dist/handlers/time.d.ts.map +1 -1
- package/dist/handlers/timers.d.ts +98 -3
- package/dist/handlers/timers.d.ts.map +1 -1
- package/dist/http.d.ts +7 -7
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +51 -40
- package/dist/http.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/oauth.d.ts +9 -9
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +39 -39
- package/dist/oauth.js.map +1 -1
- package/dist/schema.d.ts +62 -62
- package/dist/server.js +3 -3
- package/dist/server.js.map +1 -1
- package/dist/stdio.d.ts +4 -4
- package/dist/{version-DpBFJ7eV.js → version-BFw4junA.js} +2 -2
- package/dist/{version-DpBFJ7eV.js.map → version-BFw4junA.js.map} +1 -1
- package/package.json +10 -18
package/dist/handlers/time.d.ts
CHANGED
|
@@ -6,7 +6,102 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { TimeArgs } from './types.js';
|
|
8
8
|
export declare const handleTime: (action: string, args: TimeArgs & {
|
|
9
|
-
query?: string;
|
|
10
|
-
type?: import("@studiometa/productive-core").ResolvableResourceType;
|
|
11
|
-
}, ctx: import("./types.js").HandlerContext) => Promise<
|
|
9
|
+
query?: string | undefined;
|
|
10
|
+
type?: import("@studiometa/productive-core").ResolvableResourceType | undefined;
|
|
11
|
+
}, ctx: import("./types.js").HandlerContext) => Promise<{
|
|
12
|
+
[x: string]: unknown;
|
|
13
|
+
_meta?: {
|
|
14
|
+
[x: string]: unknown;
|
|
15
|
+
progressToken?: string | number | undefined;
|
|
16
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
17
|
+
taskId: string;
|
|
18
|
+
} | undefined;
|
|
19
|
+
} | undefined;
|
|
20
|
+
content: ({
|
|
21
|
+
type: "text";
|
|
22
|
+
text: string;
|
|
23
|
+
annotations?: {
|
|
24
|
+
audience?: ("assistant" | "user")[] | undefined;
|
|
25
|
+
priority?: number | undefined;
|
|
26
|
+
lastModified?: string | undefined;
|
|
27
|
+
} | undefined;
|
|
28
|
+
_meta?: {
|
|
29
|
+
[x: string]: unknown;
|
|
30
|
+
} | undefined;
|
|
31
|
+
} | {
|
|
32
|
+
type: "image";
|
|
33
|
+
data: string;
|
|
34
|
+
mimeType: string;
|
|
35
|
+
annotations?: {
|
|
36
|
+
audience?: ("assistant" | "user")[] | undefined;
|
|
37
|
+
priority?: number | undefined;
|
|
38
|
+
lastModified?: string | undefined;
|
|
39
|
+
} | undefined;
|
|
40
|
+
_meta?: {
|
|
41
|
+
[x: string]: unknown;
|
|
42
|
+
} | undefined;
|
|
43
|
+
} | {
|
|
44
|
+
type: "audio";
|
|
45
|
+
data: string;
|
|
46
|
+
mimeType: string;
|
|
47
|
+
annotations?: {
|
|
48
|
+
audience?: ("assistant" | "user")[] | undefined;
|
|
49
|
+
priority?: number | undefined;
|
|
50
|
+
lastModified?: string | undefined;
|
|
51
|
+
} | undefined;
|
|
52
|
+
_meta?: {
|
|
53
|
+
[x: string]: unknown;
|
|
54
|
+
} | undefined;
|
|
55
|
+
} | {
|
|
56
|
+
uri: string;
|
|
57
|
+
description?: string | undefined;
|
|
58
|
+
mimeType?: string | undefined;
|
|
59
|
+
annotations?: {
|
|
60
|
+
audience?: ("assistant" | "user")[] | undefined;
|
|
61
|
+
priority?: number | undefined;
|
|
62
|
+
lastModified?: string | undefined;
|
|
63
|
+
} | undefined;
|
|
64
|
+
_meta?: {
|
|
65
|
+
[x: string]: unknown;
|
|
66
|
+
} | undefined;
|
|
67
|
+
icons?: {
|
|
68
|
+
src: string;
|
|
69
|
+
mimeType?: string | undefined;
|
|
70
|
+
sizes?: string[] | undefined;
|
|
71
|
+
theme?: "dark" | "light" | undefined;
|
|
72
|
+
}[] | undefined;
|
|
73
|
+
name: string;
|
|
74
|
+
title?: string | undefined;
|
|
75
|
+
type: "resource_link";
|
|
76
|
+
} | {
|
|
77
|
+
type: "resource";
|
|
78
|
+
resource: {
|
|
79
|
+
uri: string;
|
|
80
|
+
mimeType?: string | undefined;
|
|
81
|
+
_meta?: {
|
|
82
|
+
[x: string]: unknown;
|
|
83
|
+
} | undefined;
|
|
84
|
+
text: string;
|
|
85
|
+
} | {
|
|
86
|
+
uri: string;
|
|
87
|
+
mimeType?: string | undefined;
|
|
88
|
+
_meta?: {
|
|
89
|
+
[x: string]: unknown;
|
|
90
|
+
} | undefined;
|
|
91
|
+
blob: string;
|
|
92
|
+
};
|
|
93
|
+
annotations?: {
|
|
94
|
+
audience?: ("assistant" | "user")[] | undefined;
|
|
95
|
+
priority?: number | undefined;
|
|
96
|
+
lastModified?: string | undefined;
|
|
97
|
+
} | undefined;
|
|
98
|
+
_meta?: {
|
|
99
|
+
[x: string]: unknown;
|
|
100
|
+
} | undefined;
|
|
101
|
+
})[];
|
|
102
|
+
structuredContent?: {
|
|
103
|
+
[x: string]: unknown;
|
|
104
|
+
} | undefined;
|
|
105
|
+
isError?: boolean | undefined;
|
|
106
|
+
}>;
|
|
12
107
|
//# sourceMappingURL=time.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/handlers/time.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAQ3C,eAAO,MAAM,UAAU
|
|
1
|
+
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/handlers/time.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAQ3C,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgErB,CAAC"}
|
|
@@ -3,7 +3,102 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { TimerArgs } from './types.js';
|
|
5
5
|
export declare const handleTimers: (action: string, args: TimerArgs & {
|
|
6
|
-
query?: string;
|
|
7
|
-
type?: import("@studiometa/productive-core").ResolvableResourceType;
|
|
8
|
-
}, ctx: import("./types.js").HandlerContext) => Promise<
|
|
6
|
+
query?: string | undefined;
|
|
7
|
+
type?: import("@studiometa/productive-core").ResolvableResourceType | undefined;
|
|
8
|
+
}, ctx: import("./types.js").HandlerContext) => Promise<{
|
|
9
|
+
[x: string]: unknown;
|
|
10
|
+
_meta?: {
|
|
11
|
+
[x: string]: unknown;
|
|
12
|
+
progressToken?: string | number | undefined;
|
|
13
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
14
|
+
taskId: string;
|
|
15
|
+
} | undefined;
|
|
16
|
+
} | undefined;
|
|
17
|
+
content: ({
|
|
18
|
+
type: "text";
|
|
19
|
+
text: string;
|
|
20
|
+
annotations?: {
|
|
21
|
+
audience?: ("assistant" | "user")[] | undefined;
|
|
22
|
+
priority?: number | undefined;
|
|
23
|
+
lastModified?: string | undefined;
|
|
24
|
+
} | undefined;
|
|
25
|
+
_meta?: {
|
|
26
|
+
[x: string]: unknown;
|
|
27
|
+
} | undefined;
|
|
28
|
+
} | {
|
|
29
|
+
type: "image";
|
|
30
|
+
data: string;
|
|
31
|
+
mimeType: string;
|
|
32
|
+
annotations?: {
|
|
33
|
+
audience?: ("assistant" | "user")[] | undefined;
|
|
34
|
+
priority?: number | undefined;
|
|
35
|
+
lastModified?: string | undefined;
|
|
36
|
+
} | undefined;
|
|
37
|
+
_meta?: {
|
|
38
|
+
[x: string]: unknown;
|
|
39
|
+
} | undefined;
|
|
40
|
+
} | {
|
|
41
|
+
type: "audio";
|
|
42
|
+
data: string;
|
|
43
|
+
mimeType: string;
|
|
44
|
+
annotations?: {
|
|
45
|
+
audience?: ("assistant" | "user")[] | undefined;
|
|
46
|
+
priority?: number | undefined;
|
|
47
|
+
lastModified?: string | undefined;
|
|
48
|
+
} | undefined;
|
|
49
|
+
_meta?: {
|
|
50
|
+
[x: string]: unknown;
|
|
51
|
+
} | undefined;
|
|
52
|
+
} | {
|
|
53
|
+
uri: string;
|
|
54
|
+
description?: string | undefined;
|
|
55
|
+
mimeType?: string | undefined;
|
|
56
|
+
annotations?: {
|
|
57
|
+
audience?: ("assistant" | "user")[] | undefined;
|
|
58
|
+
priority?: number | undefined;
|
|
59
|
+
lastModified?: string | undefined;
|
|
60
|
+
} | undefined;
|
|
61
|
+
_meta?: {
|
|
62
|
+
[x: string]: unknown;
|
|
63
|
+
} | undefined;
|
|
64
|
+
icons?: {
|
|
65
|
+
src: string;
|
|
66
|
+
mimeType?: string | undefined;
|
|
67
|
+
sizes?: string[] | undefined;
|
|
68
|
+
theme?: "dark" | "light" | undefined;
|
|
69
|
+
}[] | undefined;
|
|
70
|
+
name: string;
|
|
71
|
+
title?: string | undefined;
|
|
72
|
+
type: "resource_link";
|
|
73
|
+
} | {
|
|
74
|
+
type: "resource";
|
|
75
|
+
resource: {
|
|
76
|
+
uri: string;
|
|
77
|
+
mimeType?: string | undefined;
|
|
78
|
+
_meta?: {
|
|
79
|
+
[x: string]: unknown;
|
|
80
|
+
} | undefined;
|
|
81
|
+
text: string;
|
|
82
|
+
} | {
|
|
83
|
+
uri: string;
|
|
84
|
+
mimeType?: string | undefined;
|
|
85
|
+
_meta?: {
|
|
86
|
+
[x: string]: unknown;
|
|
87
|
+
} | undefined;
|
|
88
|
+
blob: string;
|
|
89
|
+
};
|
|
90
|
+
annotations?: {
|
|
91
|
+
audience?: ("assistant" | "user")[] | undefined;
|
|
92
|
+
priority?: number | undefined;
|
|
93
|
+
lastModified?: string | undefined;
|
|
94
|
+
} | undefined;
|
|
95
|
+
_meta?: {
|
|
96
|
+
[x: string]: unknown;
|
|
97
|
+
} | undefined;
|
|
98
|
+
})[];
|
|
99
|
+
structuredContent?: {
|
|
100
|
+
[x: string]: unknown;
|
|
101
|
+
} | undefined;
|
|
102
|
+
isError?: boolean | undefined;
|
|
103
|
+
}>;
|
|
9
104
|
//# sourceMappingURL=timers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timers.d.ts","sourceRoot":"","sources":["../../src/handlers/timers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAQ5C,eAAO,MAAM,YAAY
|
|
1
|
+
{"version":3,"file":"timers.d.ts","sourceRoot":"","sources":["../../src/handlers/timers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAQ5C,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqCvB,CAAC"}
|
package/dist/http.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This module contains the app/router creation logic for the HTTP transport.
|
|
5
5
|
* The actual server startup is in server.ts.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { H3 } from 'h3';
|
|
8
8
|
/**
|
|
9
9
|
* JSON-RPC error response
|
|
10
10
|
*/
|
|
@@ -44,6 +44,7 @@ export declare function handleInitialize(): {
|
|
|
44
44
|
*/
|
|
45
45
|
export declare function handleToolsList(): {
|
|
46
46
|
tools: {
|
|
47
|
+
description?: string | undefined;
|
|
47
48
|
inputSchema: {
|
|
48
49
|
[x: string]: unknown;
|
|
49
50
|
type: "object";
|
|
@@ -52,8 +53,6 @@ export declare function handleToolsList(): {
|
|
|
52
53
|
} | undefined;
|
|
53
54
|
required?: string[] | undefined;
|
|
54
55
|
};
|
|
55
|
-
name: string;
|
|
56
|
-
description?: string | undefined;
|
|
57
56
|
outputSchema?: {
|
|
58
57
|
[x: string]: unknown;
|
|
59
58
|
type: "object";
|
|
@@ -70,7 +69,7 @@ export declare function handleToolsList(): {
|
|
|
70
69
|
openWorldHint?: boolean | undefined;
|
|
71
70
|
} | undefined;
|
|
72
71
|
execution?: {
|
|
73
|
-
taskSupport?: "
|
|
72
|
+
taskSupport?: "forbidden" | "optional" | "required" | undefined;
|
|
74
73
|
} | undefined;
|
|
75
74
|
_meta?: {
|
|
76
75
|
[x: string]: unknown;
|
|
@@ -79,13 +78,14 @@ export declare function handleToolsList(): {
|
|
|
79
78
|
src: string;
|
|
80
79
|
mimeType?: string | undefined;
|
|
81
80
|
sizes?: string[] | undefined;
|
|
82
|
-
theme?: "
|
|
81
|
+
theme?: "dark" | "light" | undefined;
|
|
83
82
|
}[] | undefined;
|
|
83
|
+
name: string;
|
|
84
84
|
title?: string | undefined;
|
|
85
85
|
}[];
|
|
86
86
|
};
|
|
87
87
|
/**
|
|
88
|
-
* Create the
|
|
88
|
+
* Create the H3 application with all routes
|
|
89
89
|
*/
|
|
90
|
-
export declare function createHttpApp():
|
|
90
|
+
export declare function createHttpApp(): H3;
|
|
91
91
|
//# sourceMappingURL=http.d.ts.map
|
package/dist/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,EAAE,EAA+B,MAAM,IAAI,CAAC;AAgBrD;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,GAAE,MAAM,GAAG,MAAM,GAAG,IAAW;;;;;;;EAM5F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,GAAE,MAAM,GAAG,MAAM,GAAG,IAAW;;;;EAMhF;AAED;;GAEG;AACH,wBAAgB,gBAAgB;;;;;;;;;;;EAa/B;AAED;;GAEG;AACH,wBAAgB,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAE9B;AAWD;;GAEG;AACH,wBAAgB,aAAa,IAAI,EAAE,CA0LlC"}
|
package/dist/http.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as INSTRUCTIONS, i as readResource, n as listResourceTemplates, r as listResources, t as VERSION } from "./version-
|
|
1
|
+
import { a as INSTRUCTIONS, i as readResource, n as listResourceTemplates, r as listResources, t as VERSION } from "./version-BFw4junA.js";
|
|
2
2
|
import { t as executeToolWithCredentials } from "./handlers-t95fhdps.js";
|
|
3
3
|
import { TOOLS } from "./tools.js";
|
|
4
4
|
import { parseAuthHeader } from "./auth.js";
|
|
5
5
|
import { authorizeGetHandler, authorizePostHandler, oauthMetadataHandler, registerHandler, tokenHandler } from "./oauth.js";
|
|
6
|
-
import {
|
|
6
|
+
import { H3, defineHandler } from "h3";
|
|
7
7
|
/**
|
|
8
8
|
* HTTP transport handlers for Productive MCP Server
|
|
9
9
|
*
|
|
@@ -57,21 +57,26 @@ function handleToolsList() {
|
|
|
57
57
|
return { tools: TOOLS };
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
|
-
*
|
|
60
|
+
* Get base URL from event headers
|
|
61
|
+
*/
|
|
62
|
+
function getBaseUrl(event) {
|
|
63
|
+
const host = event.req.headers.get("host") || "localhost:3000";
|
|
64
|
+
return `${event.req.headers.get("x-forwarded-proto") || "http"}://${host}`;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create the H3 application with all routes
|
|
61
68
|
*/
|
|
62
69
|
function createHttpApp() {
|
|
63
|
-
const app =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
setResponseHeader(event, "Content-Type", "application/json");
|
|
74
|
-
setResponseHeader(event, "Cache-Control", "public, max-age=3600");
|
|
70
|
+
const app = new H3();
|
|
71
|
+
app.get("/.well-known/oauth-authorization-server", oauthMetadataHandler);
|
|
72
|
+
app.post("/register", registerHandler);
|
|
73
|
+
app.get("/authorize", authorizeGetHandler);
|
|
74
|
+
app.post("/authorize", authorizePostHandler);
|
|
75
|
+
app.post("/token", tokenHandler);
|
|
76
|
+
app.get("/.well-known/oauth-protected-resource", defineHandler((event) => {
|
|
77
|
+
const baseUrl = getBaseUrl(event);
|
|
78
|
+
event.res.headers.set("Content-Type", "application/json");
|
|
79
|
+
event.res.headers.set("Cache-Control", "public, max-age=3600");
|
|
75
80
|
return {
|
|
76
81
|
resource: `${baseUrl}/mcp`,
|
|
77
82
|
authorization_servers: [baseUrl],
|
|
@@ -79,36 +84,35 @@ function createHttpApp() {
|
|
|
79
84
|
bearer_methods_supported: ["header"]
|
|
80
85
|
};
|
|
81
86
|
}));
|
|
82
|
-
|
|
87
|
+
app.get("/", defineHandler(() => {
|
|
83
88
|
return {
|
|
84
89
|
status: "ok",
|
|
85
90
|
service: "productive-mcp",
|
|
86
91
|
version: VERSION
|
|
87
92
|
};
|
|
88
93
|
}));
|
|
89
|
-
|
|
94
|
+
app.get("/health", defineHandler(() => {
|
|
90
95
|
return { status: "ok" };
|
|
91
96
|
}));
|
|
92
|
-
|
|
93
|
-
const credentials = parseAuthHeader(
|
|
97
|
+
app.post("/mcp", defineHandler(async (event) => {
|
|
98
|
+
const credentials = parseAuthHeader(event.req.headers.get("authorization"));
|
|
94
99
|
if (!credentials) {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
event.node.res.statusCode = 401;
|
|
100
|
+
const baseUrl = getBaseUrl(event);
|
|
101
|
+
event.res.headers.set("Content-Type", "application/json");
|
|
102
|
+
event.res.headers.set("WWW-Authenticate", `Bearer resource_metadata="${baseUrl}/.well-known/oauth-protected-resource"`);
|
|
103
|
+
event.res.status = 401;
|
|
100
104
|
return jsonRpcError(-32001, "Authentication required. Provide Bearer token with base64(organizationId:apiToken:userId)");
|
|
101
105
|
}
|
|
102
|
-
|
|
106
|
+
event.res.headers.set("Content-Type", "application/json");
|
|
103
107
|
let body;
|
|
104
108
|
try {
|
|
105
|
-
body = await
|
|
109
|
+
body = await event.req.json();
|
|
106
110
|
} catch {
|
|
107
|
-
event.
|
|
111
|
+
event.res.status = 400;
|
|
108
112
|
return jsonRpcError(-32700, "Parse error: Invalid JSON");
|
|
109
113
|
}
|
|
110
114
|
if (!body || typeof body !== "object") {
|
|
111
|
-
event.
|
|
115
|
+
event.res.status = 400;
|
|
112
116
|
return jsonRpcError(-32700, "Parse error: Invalid JSON");
|
|
113
117
|
}
|
|
114
118
|
const { method, params, id } = body;
|
|
@@ -131,27 +135,34 @@ function createHttpApp() {
|
|
|
131
135
|
return jsonRpcError(-32603, `Internal error: ${error instanceof Error ? error.message : String(error)}`, id ?? null);
|
|
132
136
|
}
|
|
133
137
|
}));
|
|
134
|
-
|
|
135
|
-
if (!parseAuthHeader(
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
event.
|
|
138
|
+
app.get("/mcp/sse", defineHandler(async (event) => {
|
|
139
|
+
if (!parseAuthHeader(event.req.headers.get("authorization"))) {
|
|
140
|
+
const baseUrl = getBaseUrl(event);
|
|
141
|
+
event.res.headers.set("WWW-Authenticate", `Bearer resource_metadata="${baseUrl}/.well-known/oauth-protected-resource"`);
|
|
142
|
+
event.res.status = 401;
|
|
139
143
|
return { error: "Authentication required" };
|
|
140
144
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
145
|
+
const nodeRuntime = event.runtime?.node;
|
|
146
|
+
const nodeRes = nodeRuntime?.res;
|
|
147
|
+
if (!nodeRes) {
|
|
148
|
+
event.res.status = 501;
|
|
149
|
+
return { error: "SSE requires Node.js runtime" };
|
|
150
|
+
}
|
|
151
|
+
nodeRes.writeHead(200, {
|
|
152
|
+
"Content-Type": "text/event-stream",
|
|
153
|
+
"Cache-Control": "no-cache",
|
|
154
|
+
Connection: "keep-alive"
|
|
155
|
+
});
|
|
144
156
|
const sessionId = crypto.randomUUID();
|
|
145
|
-
|
|
157
|
+
nodeRes.write(`event: session\ndata: ${JSON.stringify({ sessionId })}\n\n`);
|
|
146
158
|
const keepAlive = setInterval(() => {
|
|
147
|
-
|
|
159
|
+
nodeRes.write(": keepalive\n\n");
|
|
148
160
|
}, 3e4);
|
|
149
|
-
|
|
161
|
+
nodeRuntime?.req.on("close", () => {
|
|
150
162
|
clearInterval(keepAlive);
|
|
151
163
|
});
|
|
152
164
|
return new Promise(() => {});
|
|
153
165
|
}));
|
|
154
|
-
app.use(router);
|
|
155
166
|
return app;
|
|
156
167
|
}
|
|
157
168
|
export { createHttpApp, handleInitialize, handleToolsList, jsonRpcError, jsonRpcSuccess };
|
package/dist/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","names":[],"sources":["../src/http.ts"],"sourcesContent":["/**\n * HTTP transport handlers for Productive MCP Server\n *\n * This module contains the app/router creation logic for the HTTP transport.\n * The actual server startup is in server.ts.\n */\n\nimport {\n createApp,\n createRouter,\n defineEventHandler,\n readBody,\n getHeader,\n setResponseHeader,\n type App,\n} from 'h3';\n\nimport { parseAuthHeader } from './auth.js';\nimport { executeToolWithCredentials } from './handlers.js';\nimport { INSTRUCTIONS } from './instructions.js';\nimport {\n oauthMetadataHandler,\n registerHandler,\n authorizeGetHandler,\n authorizePostHandler,\n tokenHandler,\n} from './oauth.js';\nimport { listResources, listResourceTemplates, readResource } from './resources.js';\nimport { TOOLS } from './tools.js';\nimport { VERSION } from './version.js';\n\n/**\n * JSON-RPC error response\n */\nexport function jsonRpcError(code: number, message: string, id: string | number | null = null) {\n return {\n jsonrpc: '2.0',\n error: { code, message },\n id,\n };\n}\n\n/**\n * JSON-RPC success response\n */\nexport function jsonRpcSuccess(result: unknown, id: string | number | null = null) {\n return {\n jsonrpc: '2.0',\n result,\n id,\n };\n}\n\n/**\n * Handle the initialize JSON-RPC method\n */\nexport function handleInitialize() {\n return {\n protocolVersion: '2024-11-05',\n serverInfo: {\n name: 'productive-mcp',\n version: VERSION,\n },\n capabilities: {\n tools: {},\n resources: {},\n },\n instructions: INSTRUCTIONS,\n };\n}\n\n/**\n * Handle the tools/list JSON-RPC method\n */\nexport function handleToolsList() {\n return { tools: TOOLS };\n}\n\n/**\n * Create the h3 application with all routes\n */\nexport function createHttpApp(): App {\n const app = createApp();\n const router = createRouter();\n\n // OAuth 2.0 endpoints for Claude Desktop integration (MCP auth spec)\n router.get('/.well-known/oauth-authorization-server', oauthMetadataHandler);\n router.post('/register', registerHandler); // Dynamic Client Registration (RFC 7591)\n router.get('/authorize', authorizeGetHandler);\n router.post('/authorize', authorizePostHandler);\n router.post('/token', tokenHandler);\n\n // OAuth Protected Resource Metadata (RFC 9728 / MCP spec 2025-03-26)\n // This endpoint tells clients where to find the authorization server\n router.get(\n '/.well-known/oauth-protected-resource',\n defineEventHandler((event) => {\n const host = event.node.req.headers.host || 'localhost:3000';\n const protocol = event.node.req.headers['x-forwarded-proto'] || 'http';\n const baseUrl = `${protocol}://${host}`;\n\n setResponseHeader(event, 'Content-Type', 'application/json');\n setResponseHeader(event, 'Cache-Control', 'public, max-age=3600');\n\n return {\n resource: `${baseUrl}/mcp`,\n authorization_servers: [baseUrl],\n scopes_supported: ['productive'],\n bearer_methods_supported: ['header'],\n };\n }),\n );\n\n // Health check endpoint\n router.get(\n '/',\n defineEventHandler(() => {\n return { status: 'ok', service: 'productive-mcp', version: VERSION };\n }),\n );\n\n router.get(\n '/health',\n defineEventHandler(() => {\n return { status: 'ok' };\n }),\n );\n\n // MCP endpoint - handles JSON-RPC over HTTP\n router.post(\n '/mcp',\n defineEventHandler(async (event) => {\n // Parse authorization header\n const authHeader = getHeader(event, 'authorization');\n const credentials = parseAuthHeader(authHeader);\n\n if (!credentials) {\n // RFC 6750: Return WWW-Authenticate header to trigger OAuth flow\n const host = event.node.req.headers.host || 'localhost:3000';\n const protocol = event.node.req.headers['x-forwarded-proto'] || 'http';\n const baseUrl = `${protocol}://${host}`;\n\n setResponseHeader(event, 'Content-Type', 'application/json');\n setResponseHeader(\n event,\n 'WWW-Authenticate',\n `Bearer resource_metadata=\"${baseUrl}/.well-known/oauth-protected-resource\"`,\n );\n event.node.res.statusCode = 401;\n return jsonRpcError(\n -32001,\n 'Authentication required. Provide Bearer token with base64(organizationId:apiToken:userId)',\n );\n }\n\n setResponseHeader(event, 'Content-Type', 'application/json');\n\n // Parse JSON-RPC request\n let body: { method?: string; params?: unknown; id?: string | number };\n try {\n body = await readBody(event);\n } catch {\n event.node.res.statusCode = 400;\n return jsonRpcError(-32700, 'Parse error: Invalid JSON');\n }\n\n if (!body || typeof body !== 'object') {\n event.node.res.statusCode = 400;\n return jsonRpcError(-32700, 'Parse error: Invalid JSON');\n }\n\n const { method, params, id } = body;\n\n try {\n if (method === 'initialize') {\n return jsonRpcSuccess(handleInitialize(), id ?? null);\n }\n\n if (method === 'tools/list') {\n return jsonRpcSuccess(handleToolsList(), id ?? null);\n }\n\n if (method === 'tools/call') {\n const { name, arguments: args } = params as {\n name: string;\n arguments?: Record<string, unknown>;\n };\n const result = await executeToolWithCredentials(name, args || {}, credentials);\n return jsonRpcSuccess(result, id ?? null);\n }\n\n if (method === 'resources/list') {\n return jsonRpcSuccess({ resources: listResources() }, id ?? null);\n }\n\n if (method === 'resources/templates/list') {\n return jsonRpcSuccess({ resourceTemplates: listResourceTemplates() }, id ?? null);\n }\n\n if (method === 'resources/read') {\n const { uri } = (params as { uri: string }) ?? {};\n if (!uri) {\n return jsonRpcError(-32602, 'Invalid params: uri is required', id ?? null);\n }\n const result = await readResource(uri, credentials);\n return jsonRpcSuccess(result, id ?? null);\n }\n\n // Unknown method\n return jsonRpcError(-32601, `Method not found: ${method}`, id ?? null);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return jsonRpcError(-32603, `Internal error: ${message}`, id ?? null);\n }\n }),\n );\n\n // SSE endpoint for server-sent events (optional, for streaming responses)\n router.get(\n '/mcp/sse',\n defineEventHandler(async (event) => {\n const authHeader = getHeader(event, 'authorization');\n const credentials = parseAuthHeader(authHeader);\n\n if (!credentials) {\n // RFC 6750: Return WWW-Authenticate header to trigger OAuth flow\n const host = event.node.req.headers.host || 'localhost:3000';\n const protocol = event.node.req.headers['x-forwarded-proto'] || 'http';\n const baseUrl = `${protocol}://${host}`;\n\n setResponseHeader(\n event,\n 'WWW-Authenticate',\n `Bearer resource_metadata=\"${baseUrl}/.well-known/oauth-protected-resource\"`,\n );\n event.node.res.statusCode = 401;\n return { error: 'Authentication required' };\n }\n\n // Set SSE headers\n setResponseHeader(event, 'Content-Type', 'text/event-stream');\n setResponseHeader(event, 'Cache-Control', 'no-cache');\n setResponseHeader(event, 'Connection', 'keep-alive');\n\n // Generate session ID and send it\n const sessionId = crypto.randomUUID();\n\n // Send initial session event\n event.node.res.write(`event: session\\ndata: ${JSON.stringify({ sessionId })}\\n\\n`);\n\n // Keep connection alive\n const keepAlive = setInterval(() => {\n event.node.res.write(': keepalive\\n\\n');\n }, 30000);\n\n // Clean up on close\n event.node.req.on('close', () => {\n clearInterval(keepAlive);\n });\n\n // Don't end the response - keep it open for SSE\n return new Promise(() => {});\n }),\n );\n\n app.use(router);\n return app;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"http.js","names":[],"sources":["../src/http.ts"],"sourcesContent":["/**\n * HTTP transport handlers for Productive MCP Server\n *\n * This module contains the app/router creation logic for the HTTP transport.\n * The actual server startup is in server.ts.\n */\n\nimport { H3, defineHandler, type H3Event } from 'h3';\n\nimport { parseAuthHeader } from './auth.js';\nimport { executeToolWithCredentials } from './handlers.js';\nimport { INSTRUCTIONS } from './instructions.js';\nimport {\n oauthMetadataHandler,\n registerHandler,\n authorizeGetHandler,\n authorizePostHandler,\n tokenHandler,\n} from './oauth.js';\nimport { listResources, listResourceTemplates, readResource } from './resources.js';\nimport { TOOLS } from './tools.js';\nimport { VERSION } from './version.js';\n\n/**\n * JSON-RPC error response\n */\nexport function jsonRpcError(code: number, message: string, id: string | number | null = null) {\n return {\n jsonrpc: '2.0',\n error: { code, message },\n id,\n };\n}\n\n/**\n * JSON-RPC success response\n */\nexport function jsonRpcSuccess(result: unknown, id: string | number | null = null) {\n return {\n jsonrpc: '2.0',\n result,\n id,\n };\n}\n\n/**\n * Handle the initialize JSON-RPC method\n */\nexport function handleInitialize() {\n return {\n protocolVersion: '2024-11-05',\n serverInfo: {\n name: 'productive-mcp',\n version: VERSION,\n },\n capabilities: {\n tools: {},\n resources: {},\n },\n instructions: INSTRUCTIONS,\n };\n}\n\n/**\n * Handle the tools/list JSON-RPC method\n */\nexport function handleToolsList() {\n return { tools: TOOLS };\n}\n\n/**\n * Get base URL from event headers\n */\nfunction getBaseUrl(event: H3Event): string {\n const host = event.req.headers.get('host') || 'localhost:3000';\n const protocol = event.req.headers.get('x-forwarded-proto') || 'http';\n return `${protocol}://${host}`;\n}\n\n/**\n * Create the H3 application with all routes\n */\nexport function createHttpApp(): H3 {\n const app = new H3();\n\n // OAuth 2.0 endpoints for Claude Desktop integration (MCP auth spec)\n app.get('/.well-known/oauth-authorization-server', oauthMetadataHandler);\n app.post('/register', registerHandler); // Dynamic Client Registration (RFC 7591)\n app.get('/authorize', authorizeGetHandler);\n app.post('/authorize', authorizePostHandler);\n app.post('/token', tokenHandler);\n\n // OAuth Protected Resource Metadata (RFC 9728 / MCP spec 2025-03-26)\n // This endpoint tells clients where to find the authorization server\n app.get(\n '/.well-known/oauth-protected-resource',\n defineHandler((event) => {\n const baseUrl = getBaseUrl(event);\n\n event.res.headers.set('Content-Type', 'application/json');\n event.res.headers.set('Cache-Control', 'public, max-age=3600');\n\n return {\n resource: `${baseUrl}/mcp`,\n authorization_servers: [baseUrl],\n scopes_supported: ['productive'],\n bearer_methods_supported: ['header'],\n };\n }),\n );\n\n // Health check endpoint\n app.get(\n '/',\n defineHandler(() => {\n return { status: 'ok', service: 'productive-mcp', version: VERSION };\n }),\n );\n\n app.get(\n '/health',\n defineHandler(() => {\n return { status: 'ok' };\n }),\n );\n\n // MCP endpoint - handles JSON-RPC over HTTP\n app.post(\n '/mcp',\n defineHandler(async (event) => {\n // Parse authorization header\n const authHeader = event.req.headers.get('authorization');\n const credentials = parseAuthHeader(authHeader);\n\n if (!credentials) {\n // RFC 6750: Return WWW-Authenticate header to trigger OAuth flow\n const baseUrl = getBaseUrl(event);\n\n event.res.headers.set('Content-Type', 'application/json');\n event.res.headers.set(\n 'WWW-Authenticate',\n `Bearer resource_metadata=\"${baseUrl}/.well-known/oauth-protected-resource\"`,\n );\n event.res.status = 401;\n return jsonRpcError(\n -32001,\n 'Authentication required. Provide Bearer token with base64(organizationId:apiToken:userId)',\n );\n }\n\n event.res.headers.set('Content-Type', 'application/json');\n\n // Parse JSON-RPC request\n let body: { method?: string; params?: unknown; id?: string | number } | undefined;\n try {\n body = await event.req.json();\n } catch {\n event.res.status = 400;\n return jsonRpcError(-32700, 'Parse error: Invalid JSON');\n }\n\n if (!body || typeof body !== 'object') {\n event.res.status = 400;\n return jsonRpcError(-32700, 'Parse error: Invalid JSON');\n }\n\n const { method, params, id } = body;\n\n try {\n if (method === 'initialize') {\n return jsonRpcSuccess(handleInitialize(), id ?? null);\n }\n\n if (method === 'tools/list') {\n return jsonRpcSuccess(handleToolsList(), id ?? null);\n }\n\n if (method === 'tools/call') {\n const { name, arguments: args } = params as {\n name: string;\n arguments?: Record<string, unknown>;\n };\n const result = await executeToolWithCredentials(name, args || {}, credentials);\n return jsonRpcSuccess(result, id ?? null);\n }\n\n if (method === 'resources/list') {\n return jsonRpcSuccess({ resources: listResources() }, id ?? null);\n }\n\n if (method === 'resources/templates/list') {\n return jsonRpcSuccess({ resourceTemplates: listResourceTemplates() }, id ?? null);\n }\n\n if (method === 'resources/read') {\n const { uri } = (params as { uri: string }) ?? {};\n if (!uri) {\n return jsonRpcError(-32602, 'Invalid params: uri is required', id ?? null);\n }\n const result = await readResource(uri, credentials);\n return jsonRpcSuccess(result, id ?? null);\n }\n\n // Unknown method\n return jsonRpcError(-32601, `Method not found: ${method}`, id ?? null);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return jsonRpcError(-32603, `Internal error: ${message}`, id ?? null);\n }\n }),\n );\n\n // SSE endpoint for server-sent events (optional, for streaming responses)\n app.get(\n '/mcp/sse',\n defineHandler(async (event) => {\n const authHeader = event.req.headers.get('authorization');\n const credentials = parseAuthHeader(authHeader);\n\n if (!credentials) {\n // RFC 6750: Return WWW-Authenticate header to trigger OAuth flow\n const baseUrl = getBaseUrl(event);\n\n event.res.headers.set(\n 'WWW-Authenticate',\n `Bearer resource_metadata=\"${baseUrl}/.well-known/oauth-protected-resource\"`,\n );\n event.res.status = 401;\n return { error: 'Authentication required' };\n }\n\n // Node.js-specific SSE: access raw res for streaming\n const nodeRuntime = event.runtime?.node;\n const nodeRes = nodeRuntime?.res as import('node:http').ServerResponse | undefined;\n if (!nodeRes) {\n event.res.status = 501;\n return { error: 'SSE requires Node.js runtime' };\n }\n\n // Write SSE headers directly to Node.js response (bypassing h3's pipeline)\n nodeRes.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive',\n });\n\n // Generate session ID and send it\n const sessionId = crypto.randomUUID();\n\n // Send initial session event\n nodeRes.write(`event: session\\ndata: ${JSON.stringify({ sessionId })}\\n\\n`);\n\n // Keep connection alive\n const keepAlive = setInterval(() => {\n nodeRes.write(': keepalive\\n\\n');\n }, 30000);\n\n // Clean up on close\n nodeRuntime?.req.on('close', () => {\n clearInterval(keepAlive);\n });\n\n // Don't end the response - keep it open for SSE\n return new Promise(() => {});\n }),\n );\n\n return app;\n}\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as INSTRUCTIONS, i as readResource, n as listResourceTemplates, r as listResources, t as VERSION } from "./version-
|
|
2
|
+
import { a as INSTRUCTIONS, i as readResource, n as listResourceTemplates, r as listResources, t as VERSION } from "./version-BFw4junA.js";
|
|
3
3
|
import "./handlers-t95fhdps.js";
|
|
4
4
|
import { a as handlePrompt, n as getAvailableTools, s as handleToolCall, t as getAvailablePrompts } from "./stdio-Bi1Lvp8O.js";
|
|
5
5
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
package/dist/oauth.d.ts
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*
|
|
21
21
|
* MCP clients MUST check this endpoint first for server capabilities.
|
|
22
22
|
*/
|
|
23
|
-
export declare const oauthMetadataHandler: import("h3").
|
|
23
|
+
export declare const oauthMetadataHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, {
|
|
24
24
|
issuer: string;
|
|
25
25
|
authorization_endpoint: string;
|
|
26
26
|
token_endpoint: string;
|
|
@@ -40,7 +40,7 @@ export declare const oauthMetadataHandler: import("h3").EventHandler<import("h3"
|
|
|
40
40
|
* Since we use stateless tokens, we accept any registration and return
|
|
41
41
|
* a generated client_id.
|
|
42
42
|
*/
|
|
43
|
-
export declare const registerHandler: import("h3").
|
|
43
|
+
export declare const registerHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
44
44
|
error: string;
|
|
45
45
|
error_description: string;
|
|
46
46
|
client_id?: undefined;
|
|
@@ -50,25 +50,25 @@ export declare const registerHandler: import("h3").EventHandler<import("h3").Eve
|
|
|
50
50
|
grant_types?: undefined;
|
|
51
51
|
response_types?: undefined;
|
|
52
52
|
} | {
|
|
53
|
+
error?: undefined;
|
|
54
|
+
error_description?: undefined;
|
|
53
55
|
client_id: string;
|
|
54
56
|
client_name: string;
|
|
55
57
|
redirect_uris: string[];
|
|
56
58
|
token_endpoint_auth_method: string;
|
|
57
59
|
grant_types: string[];
|
|
58
60
|
response_types: string[];
|
|
59
|
-
error?: undefined;
|
|
60
|
-
error_description?: undefined;
|
|
61
61
|
}>>;
|
|
62
62
|
/**
|
|
63
63
|
* Authorization endpoint - shows login form
|
|
64
64
|
* GET /authorize
|
|
65
65
|
*/
|
|
66
|
-
export declare const authorizeGetHandler: import("h3").
|
|
66
|
+
export declare const authorizeGetHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, string | import("h3").HTTPResponse>;
|
|
67
67
|
/**
|
|
68
68
|
* Authorization endpoint - process login
|
|
69
69
|
* POST /authorize
|
|
70
70
|
*/
|
|
71
|
-
export declare const authorizePostHandler: import("h3").
|
|
71
|
+
export declare const authorizePostHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<string>>;
|
|
72
72
|
/**
|
|
73
73
|
* Token endpoint - exchange code for access token
|
|
74
74
|
* POST /token
|
|
@@ -77,7 +77,7 @@ export declare const authorizePostHandler: import("h3").EventHandler<import("h3"
|
|
|
77
77
|
* - authorization_code grant (with PKCE validation)
|
|
78
78
|
* - refresh_token grant
|
|
79
79
|
*/
|
|
80
|
-
export declare const tokenHandler: import("h3").
|
|
80
|
+
export declare const tokenHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
81
81
|
error: string;
|
|
82
82
|
error_description: string;
|
|
83
83
|
access_token?: undefined;
|
|
@@ -85,11 +85,11 @@ export declare const tokenHandler: import("h3").EventHandler<import("h3").EventH
|
|
|
85
85
|
expires_in?: undefined;
|
|
86
86
|
refresh_token?: undefined;
|
|
87
87
|
} | {
|
|
88
|
+
error?: undefined;
|
|
89
|
+
error_description?: undefined;
|
|
88
90
|
access_token: string;
|
|
89
91
|
token_type: string;
|
|
90
92
|
expires_in: number;
|
|
91
93
|
refresh_token: string;
|
|
92
|
-
error?: undefined;
|
|
93
|
-
error_description?: undefined;
|
|
94
94
|
}>>;
|
|
95
95
|
//# sourceMappingURL=oauth.d.ts.map
|
package/dist/oauth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;EAyB/B,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;GAoC1B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mBAAmB,0GA+C9B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,oBAAoB,uFA0D/B,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;GA2FvB,CAAC"}
|