@mcp-z/oauth 1.0.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/LICENSE +21 -0
- package/README.md +71 -0
- package/dist/cjs/account-utils.d.cts +107 -0
- package/dist/cjs/account-utils.d.ts +107 -0
- package/dist/cjs/account-utils.js +481 -0
- package/dist/cjs/account-utils.js.map +1 -0
- package/dist/cjs/index.d.cts +19 -0
- package/dist/cjs/index.d.ts +19 -0
- package/dist/cjs/index.js +149 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/jwt-auth.d.cts +53 -0
- package/dist/cjs/jwt-auth.d.ts +53 -0
- package/dist/cjs/jwt-auth.js +417 -0
- package/dist/cjs/jwt-auth.js.map +1 -0
- package/dist/cjs/key-utils.d.cts +131 -0
- package/dist/cjs/key-utils.d.ts +131 -0
- package/dist/cjs/key-utils.js +421 -0
- package/dist/cjs/key-utils.js.map +1 -0
- package/dist/cjs/lib/account-server/index.d.cts +45 -0
- package/dist/cjs/lib/account-server/index.d.ts +45 -0
- package/dist/cjs/lib/account-server/index.js +67 -0
- package/dist/cjs/lib/account-server/index.js.map +1 -0
- package/dist/cjs/lib/account-server/loopback.d.cts +22 -0
- package/dist/cjs/lib/account-server/loopback.d.ts +22 -0
- package/dist/cjs/lib/account-server/loopback.js +778 -0
- package/dist/cjs/lib/account-server/loopback.js.map +1 -0
- package/dist/cjs/lib/account-server/me.d.cts +23 -0
- package/dist/cjs/lib/account-server/me.d.ts +23 -0
- package/dist/cjs/lib/account-server/me.js +412 -0
- package/dist/cjs/lib/account-server/me.js.map +1 -0
- package/dist/cjs/lib/account-server/shared-utils.d.cts +6 -0
- package/dist/cjs/lib/account-server/shared-utils.d.ts +6 -0
- package/dist/cjs/lib/account-server/shared-utils.js +235 -0
- package/dist/cjs/lib/account-server/shared-utils.js.map +1 -0
- package/dist/cjs/lib/account-server/stateless.d.cts +20 -0
- package/dist/cjs/lib/account-server/stateless.d.ts +20 -0
- package/dist/cjs/lib/account-server/stateless.js +32 -0
- package/dist/cjs/lib/account-server/stateless.js.map +1 -0
- package/dist/cjs/lib/account-server/types.d.cts +32 -0
- package/dist/cjs/lib/account-server/types.d.ts +32 -0
- package/dist/cjs/lib/account-server/types.js +7 -0
- package/dist/cjs/lib/account-server/types.js.map +1 -0
- package/dist/cjs/lib/dcr-types.d.cts +126 -0
- package/dist/cjs/lib/dcr-types.d.ts +126 -0
- package/dist/cjs/lib/dcr-types.js +12 -0
- package/dist/cjs/lib/dcr-types.js.map +1 -0
- package/dist/cjs/lib/rfc-metadata-types.d.cts +46 -0
- package/dist/cjs/lib/rfc-metadata-types.d.ts +46 -0
- package/dist/cjs/lib/rfc-metadata-types.js +8 -0
- package/dist/cjs/lib/rfc-metadata-types.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/pkce.d.cts +36 -0
- package/dist/cjs/pkce.d.ts +36 -0
- package/dist/cjs/pkce.js +25 -0
- package/dist/cjs/pkce.js.map +1 -0
- package/dist/cjs/sanitizer.d.cts +37 -0
- package/dist/cjs/sanitizer.d.ts +37 -0
- package/dist/cjs/sanitizer.js +407 -0
- package/dist/cjs/sanitizer.js.map +1 -0
- package/dist/cjs/schemas/index.d.cts +36 -0
- package/dist/cjs/schemas/index.d.ts +36 -0
- package/dist/cjs/schemas/index.js +28 -0
- package/dist/cjs/schemas/index.js.map +1 -0
- package/dist/cjs/session-auth.d.cts +79 -0
- package/dist/cjs/session-auth.d.ts +79 -0
- package/dist/cjs/session-auth.js +354 -0
- package/dist/cjs/session-auth.js.map +1 -0
- package/dist/cjs/templates.d.cts +18 -0
- package/dist/cjs/templates.d.ts +18 -0
- package/dist/cjs/templates.js +38 -0
- package/dist/cjs/templates.js.map +1 -0
- package/dist/cjs/types.d.cts +343 -0
- package/dist/cjs/types.d.ts +343 -0
- package/dist/cjs/types.js +210 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/account-utils.d.ts +107 -0
- package/dist/esm/account-utils.js +179 -0
- package/dist/esm/account-utils.js.map +1 -0
- package/dist/esm/index.d.ts +19 -0
- package/dist/esm/index.js +23 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/jwt-auth.d.ts +53 -0
- package/dist/esm/jwt-auth.js +164 -0
- package/dist/esm/jwt-auth.js.map +1 -0
- package/dist/esm/key-utils.d.ts +131 -0
- package/dist/esm/key-utils.js +143 -0
- package/dist/esm/key-utils.js.map +1 -0
- package/dist/esm/lib/account-server/index.d.ts +45 -0
- package/dist/esm/lib/account-server/index.js +41 -0
- package/dist/esm/lib/account-server/index.js.map +1 -0
- package/dist/esm/lib/account-server/loopback.d.ts +22 -0
- package/dist/esm/lib/account-server/loopback.js +372 -0
- package/dist/esm/lib/account-server/loopback.js.map +1 -0
- package/dist/esm/lib/account-server/me.d.ts +23 -0
- package/dist/esm/lib/account-server/me.js +170 -0
- package/dist/esm/lib/account-server/me.js.map +1 -0
- package/dist/esm/lib/account-server/shared-utils.d.ts +6 -0
- package/dist/esm/lib/account-server/shared-utils.js +24 -0
- package/dist/esm/lib/account-server/shared-utils.js.map +1 -0
- package/dist/esm/lib/account-server/stateless.d.ts +20 -0
- package/dist/esm/lib/account-server/stateless.js +25 -0
- package/dist/esm/lib/account-server/stateless.js.map +1 -0
- package/dist/esm/lib/account-server/types.d.ts +32 -0
- package/dist/esm/lib/account-server/types.js +6 -0
- package/dist/esm/lib/account-server/types.js.map +1 -0
- package/dist/esm/lib/dcr-types.d.ts +126 -0
- package/dist/esm/lib/dcr-types.js +13 -0
- package/dist/esm/lib/dcr-types.js.map +1 -0
- package/dist/esm/lib/rfc-metadata-types.d.ts +46 -0
- package/dist/esm/lib/rfc-metadata-types.js +7 -0
- package/dist/esm/lib/rfc-metadata-types.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/pkce.d.ts +36 -0
- package/dist/esm/pkce.js +33 -0
- package/dist/esm/pkce.js.map +1 -0
- package/dist/esm/sanitizer.d.ts +37 -0
- package/dist/esm/sanitizer.js +256 -0
- package/dist/esm/sanitizer.js.map +1 -0
- package/dist/esm/schemas/index.d.ts +36 -0
- package/dist/esm/schemas/index.js +19 -0
- package/dist/esm/schemas/index.js.map +1 -0
- package/dist/esm/session-auth.d.ts +79 -0
- package/dist/esm/session-auth.js +141 -0
- package/dist/esm/session-auth.js.map +1 -0
- package/dist/esm/templates.d.ts +18 -0
- package/dist/esm/templates.js +132 -0
- package/dist/esm/templates.js.map +1 -0
- package/dist/esm/types.d.ts +343 -0
- package/dist/esm/types.js +34 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML templates for OAuth callback pages
|
|
3
|
+
*
|
|
4
|
+
* These templates are shown in the browser after OAuth authorization
|
|
5
|
+
* for loopback OAuth flows (RFC 8252).
|
|
6
|
+
*/ /**
|
|
7
|
+
* HTML template for successful OAuth authorization
|
|
8
|
+
*/ export function getSuccessTemplate() {
|
|
9
|
+
return `
|
|
10
|
+
<!DOCTYPE html>
|
|
11
|
+
<html>
|
|
12
|
+
<head>
|
|
13
|
+
<meta charset="utf-8">
|
|
14
|
+
<title>Authorization Successful</title>
|
|
15
|
+
<style>
|
|
16
|
+
body {
|
|
17
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
18
|
+
display: flex;
|
|
19
|
+
justify-content: center;
|
|
20
|
+
align-items: center;
|
|
21
|
+
height: 100vh;
|
|
22
|
+
margin: 0;
|
|
23
|
+
background: linear-gradient(135deg, #e8ebf7 0%, #ede9f2 100%);
|
|
24
|
+
}
|
|
25
|
+
.container {
|
|
26
|
+
background: white;
|
|
27
|
+
padding: 3rem;
|
|
28
|
+
border-radius: 1rem;
|
|
29
|
+
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
|
|
30
|
+
text-align: center;
|
|
31
|
+
max-width: 400px;
|
|
32
|
+
}
|
|
33
|
+
h1 {
|
|
34
|
+
color: #2d3748;
|
|
35
|
+
margin-bottom: 1rem;
|
|
36
|
+
font-size: 1.875rem;
|
|
37
|
+
}
|
|
38
|
+
p {
|
|
39
|
+
color: #718096;
|
|
40
|
+
font-size: 1.125rem;
|
|
41
|
+
margin-bottom: 1.5rem;
|
|
42
|
+
}
|
|
43
|
+
.icon {
|
|
44
|
+
font-size: 4rem;
|
|
45
|
+
margin-bottom: 1rem;
|
|
46
|
+
}
|
|
47
|
+
</style>
|
|
48
|
+
</head>
|
|
49
|
+
<body>
|
|
50
|
+
<div class="container">
|
|
51
|
+
<div class="icon">✅</div>
|
|
52
|
+
<h1>Authorization Successful!</h1>
|
|
53
|
+
<p>You can close this window and return to your terminal.</p>
|
|
54
|
+
</div>
|
|
55
|
+
<script>
|
|
56
|
+
// Auto-close after 3 seconds
|
|
57
|
+
setTimeout(() => {
|
|
58
|
+
window.close();
|
|
59
|
+
}, 3000);
|
|
60
|
+
</script>
|
|
61
|
+
</body>
|
|
62
|
+
</html>
|
|
63
|
+
`.trim();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* HTML template for OAuth error
|
|
67
|
+
*/ export function getErrorTemplate(error) {
|
|
68
|
+
return `
|
|
69
|
+
<!DOCTYPE html>
|
|
70
|
+
<html>
|
|
71
|
+
<head>
|
|
72
|
+
<meta charset="utf-8">
|
|
73
|
+
<title>Authorization Failed</title>
|
|
74
|
+
<style>
|
|
75
|
+
body {
|
|
76
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
77
|
+
display: flex;
|
|
78
|
+
justify-content: center;
|
|
79
|
+
align-items: center;
|
|
80
|
+
height: 100vh;
|
|
81
|
+
margin: 0;
|
|
82
|
+
background: linear-gradient(135deg, #fce9f7 0%, #faebed 100%);
|
|
83
|
+
}
|
|
84
|
+
.container {
|
|
85
|
+
background: white;
|
|
86
|
+
padding: 3rem;
|
|
87
|
+
border-radius: 1rem;
|
|
88
|
+
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
|
|
89
|
+
text-align: center;
|
|
90
|
+
max-width: 400px;
|
|
91
|
+
}
|
|
92
|
+
h1 {
|
|
93
|
+
color: #2d3748;
|
|
94
|
+
margin-bottom: 1rem;
|
|
95
|
+
font-size: 1.875rem;
|
|
96
|
+
}
|
|
97
|
+
p {
|
|
98
|
+
color: #718096;
|
|
99
|
+
font-size: 1.125rem;
|
|
100
|
+
margin-bottom: 1.5rem;
|
|
101
|
+
}
|
|
102
|
+
.error {
|
|
103
|
+
background: #fed7d7;
|
|
104
|
+
color: #9b2c2c;
|
|
105
|
+
padding: 0.75rem;
|
|
106
|
+
border-radius: 0.5rem;
|
|
107
|
+
margin-top: 1rem;
|
|
108
|
+
font-family: monospace;
|
|
109
|
+
font-size: 0.875rem;
|
|
110
|
+
}
|
|
111
|
+
.icon {
|
|
112
|
+
font-size: 4rem;
|
|
113
|
+
margin-bottom: 1rem;
|
|
114
|
+
}
|
|
115
|
+
</style>
|
|
116
|
+
</head>
|
|
117
|
+
<body>
|
|
118
|
+
<div class="container">
|
|
119
|
+
<div class="icon">❌</div>
|
|
120
|
+
<h1>Authorization Failed</h1>
|
|
121
|
+
<p>Please try again from your terminal.</p>
|
|
122
|
+
<div class="error">${escapeHtml(error)}</div>
|
|
123
|
+
</div>
|
|
124
|
+
</body>
|
|
125
|
+
</html>
|
|
126
|
+
`.trim();
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Escape HTML special characters to prevent XSS
|
|
130
|
+
*/ export function escapeHtml(unsafe) {
|
|
131
|
+
return unsafe.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
132
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/oauth/oauth/src/templates.ts"],"sourcesContent":["/**\n * HTML templates for OAuth callback pages\n *\n * These templates are shown in the browser after OAuth authorization\n * for loopback OAuth flows (RFC 8252).\n */\n\n/**\n * HTML template for successful OAuth authorization\n */\nexport function getSuccessTemplate(): string {\n return `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Authorization Successful</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n background: linear-gradient(135deg, #e8ebf7 0%, #ede9f2 100%);\n }\n .container {\n background: white;\n padding: 3rem;\n border-radius: 1rem;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n text-align: center;\n max-width: 400px;\n }\n h1 {\n color: #2d3748;\n margin-bottom: 1rem;\n font-size: 1.875rem;\n }\n p {\n color: #718096;\n font-size: 1.125rem;\n margin-bottom: 1.5rem;\n }\n .icon {\n font-size: 4rem;\n margin-bottom: 1rem;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"icon\">✅</div>\n <h1>Authorization Successful!</h1>\n <p>You can close this window and return to your terminal.</p>\n </div>\n <script>\n // Auto-close after 3 seconds\n setTimeout(() => {\n window.close();\n }, 3000);\n </script>\n</body>\n</html>\n `.trim();\n}\n\n/**\n * HTML template for OAuth error\n */\nexport function getErrorTemplate(error: string): string {\n return `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Authorization Failed</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n background: linear-gradient(135deg, #fce9f7 0%, #faebed 100%);\n }\n .container {\n background: white;\n padding: 3rem;\n border-radius: 1rem;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n text-align: center;\n max-width: 400px;\n }\n h1 {\n color: #2d3748;\n margin-bottom: 1rem;\n font-size: 1.875rem;\n }\n p {\n color: #718096;\n font-size: 1.125rem;\n margin-bottom: 1.5rem;\n }\n .error {\n background: #fed7d7;\n color: #9b2c2c;\n padding: 0.75rem;\n border-radius: 0.5rem;\n margin-top: 1rem;\n font-family: monospace;\n font-size: 0.875rem;\n }\n .icon {\n font-size: 4rem;\n margin-bottom: 1rem;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"icon\">❌</div>\n <h1>Authorization Failed</h1>\n <p>Please try again from your terminal.</p>\n <div class=\"error\">${escapeHtml(error)}</div>\n </div>\n</body>\n</html>\n `.trim();\n}\n\n/**\n * Escape HTML special characters to prevent XSS\n */\nexport function escapeHtml(unsafe: string): string {\n return unsafe.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"').replace(/'/g, ''');\n}\n"],"names":["getSuccessTemplate","trim","getErrorTemplate","error","escapeHtml","unsafe","replace"],"mappings":"AAAA;;;;;CAKC,GAED;;CAEC,GACD,OAAO,SAASA;IACd,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsDR,CAAC,CAACC,IAAI;AACR;AAEA;;CAEC,GACD,OAAO,SAASC,iBAAiBC,KAAa;IAC5C,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAsDa,EAAEC,WAAWD,OAAO;;;;EAIzC,CAAC,CAACF,IAAI;AACR;AAEA;;CAEC,GACD,OAAO,SAASG,WAAWC,MAAc;IACvC,OAAOA,OAAOC,OAAO,CAAC,MAAM,SAASA,OAAO,CAAC,MAAM,QAAQA,OAAO,CAAC,MAAM,QAAQA,OAAO,CAAC,MAAM,UAAUA,OAAO,CAAC,MAAM;AACzH"}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for multi-account management and OAuth integration
|
|
3
|
+
*/
|
|
4
|
+
import type { AnySchema, ZodRawShapeCompat } from '@modelcontextprotocol/sdk/server/zod-compat.js';
|
|
5
|
+
import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
6
|
+
import type { CallToolResult, GetPromptResult, ServerNotification, ServerRequest, ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
|
|
7
|
+
export type Logger = Pick<Console, 'info' | 'error' | 'warn' | 'debug'>;
|
|
8
|
+
export interface AccountInfo {
|
|
9
|
+
email: string;
|
|
10
|
+
alias?: string;
|
|
11
|
+
addedAt: string;
|
|
12
|
+
lastUsed?: string;
|
|
13
|
+
metadata?: {
|
|
14
|
+
name?: string;
|
|
15
|
+
picture?: string;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* MCP tool module definition with configuration and handler function.
|
|
21
|
+
*
|
|
22
|
+
* Represents a registered tool in the Model Context Protocol server that can be
|
|
23
|
+
* invoked by MCP clients. Tools are the primary mechanism for executing operations
|
|
24
|
+
* in response to client requests.
|
|
25
|
+
*
|
|
26
|
+
* @property name - Unique tool identifier (e.g., "gmail-message-send", "sheets-values-get")
|
|
27
|
+
* @property config - Tool configuration including description and schemas
|
|
28
|
+
* @property config.description - Human-readable description shown to MCP clients
|
|
29
|
+
* @property config.inputSchema - Zod schema defining tool arguments (JSON-serializable)
|
|
30
|
+
* @property config.outputSchema - Zod schema defining tool response structure
|
|
31
|
+
* @property handler - Async function that executes the tool operation
|
|
32
|
+
*
|
|
33
|
+
* @remarks
|
|
34
|
+
* This is the runtime representation of an MCP tool after registration. The handler
|
|
35
|
+
* receives JSON-serializable arguments validated against inputSchema and returns
|
|
36
|
+
* a CallToolResult validated against outputSchema.
|
|
37
|
+
*
|
|
38
|
+
* Tools are typically created using tool factory functions and registered with the
|
|
39
|
+
* MCP server during initialization.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const tool: McpTool = {
|
|
44
|
+
* name: "gmail-message-send",
|
|
45
|
+
* config: {
|
|
46
|
+
* description: "Send an email message",
|
|
47
|
+
* inputSchema: { to: { type: "string" }, subject: { type: "string" } },
|
|
48
|
+
* outputSchema: { result: { type: "object" } }
|
|
49
|
+
* },
|
|
50
|
+
* handler: async (args, context) => {
|
|
51
|
+
* // Implementation
|
|
52
|
+
* return { content: [{ type: "text", text: "Message sent" }] };
|
|
53
|
+
* }
|
|
54
|
+
* };
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @see {@link McpPrompt} for prompt module definition
|
|
58
|
+
*/
|
|
59
|
+
export interface McpTool {
|
|
60
|
+
name: string;
|
|
61
|
+
config: {
|
|
62
|
+
description: string;
|
|
63
|
+
inputSchema: Record<string, unknown>;
|
|
64
|
+
outputSchema: Record<string, unknown>;
|
|
65
|
+
};
|
|
66
|
+
handler: (args: unknown, context?: unknown) => Promise<CallToolResult>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* MCP prompt module definition with configuration and handler function.
|
|
70
|
+
*
|
|
71
|
+
* Represents a registered prompt template in the Model Context Protocol server that
|
|
72
|
+
* can be retrieved and rendered by MCP clients. Prompts provide reusable templates
|
|
73
|
+
* for common interaction patterns.
|
|
74
|
+
*
|
|
75
|
+
* @property name - Unique prompt identifier (e.g., "draft-email", "summarize-thread")
|
|
76
|
+
* @property config - Prompt configuration (schema and metadata are prompt-specific)
|
|
77
|
+
* @property handler - Async function that generates the prompt content
|
|
78
|
+
*
|
|
79
|
+
* @remarks
|
|
80
|
+
* This is the runtime representation of an MCP prompt after registration. Unlike
|
|
81
|
+
* {@link McpTool} which executes operations, prompts generate templated content
|
|
82
|
+
* that clients can use to structure interactions.
|
|
83
|
+
*
|
|
84
|
+
* The handler receives optional arguments and returns a GetPromptResult containing
|
|
85
|
+
* the rendered prompt messages.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* const prompt: McpPrompt = {
|
|
90
|
+
* name: "draft-email",
|
|
91
|
+
* config: {
|
|
92
|
+
* description: "Generate email draft from key points",
|
|
93
|
+
* arguments: [{ name: "points", description: "Key points to include" }]
|
|
94
|
+
* },
|
|
95
|
+
* handler: async (args) => {
|
|
96
|
+
* const points = args?.points || [];
|
|
97
|
+
* return {
|
|
98
|
+
* messages: [{
|
|
99
|
+
* role: "user",
|
|
100
|
+
* content: { type: "text", text: `Draft email covering: ${points.join(", ")}` }
|
|
101
|
+
* }]
|
|
102
|
+
* };
|
|
103
|
+
* }
|
|
104
|
+
* };
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
* @see {@link McpTool} for tool module definition
|
|
108
|
+
*/
|
|
109
|
+
export interface McpPrompt {
|
|
110
|
+
name: string;
|
|
111
|
+
config: unknown;
|
|
112
|
+
handler: (args: unknown) => Promise<GetPromptResult>;
|
|
113
|
+
}
|
|
114
|
+
export declare class AccountManagerError extends Error {
|
|
115
|
+
code: string;
|
|
116
|
+
retryable: boolean;
|
|
117
|
+
constructor(message: string, code: string, retryable?: boolean);
|
|
118
|
+
}
|
|
119
|
+
export declare class AccountNotFoundError extends AccountManagerError {
|
|
120
|
+
constructor(accountRef: string);
|
|
121
|
+
}
|
|
122
|
+
export declare class ConfigurationError extends AccountManagerError {
|
|
123
|
+
constructor(message: string);
|
|
124
|
+
}
|
|
125
|
+
export declare class RequiresAuthenticationError extends AccountManagerError {
|
|
126
|
+
accountId: string | undefined;
|
|
127
|
+
constructor(service: string, accountId?: string);
|
|
128
|
+
}
|
|
129
|
+
export interface AuthEmailProvider {
|
|
130
|
+
getUserEmail(accountId?: string): Promise<string>;
|
|
131
|
+
authenticateNewAccount?(): Promise<string>;
|
|
132
|
+
}
|
|
133
|
+
export interface UserAuthProvider {
|
|
134
|
+
getUserId(req: unknown): Promise<string>;
|
|
135
|
+
}
|
|
136
|
+
export interface JWTUserAuthConfig {
|
|
137
|
+
secret?: string;
|
|
138
|
+
publicKey?: string | object;
|
|
139
|
+
jwksUrl?: string;
|
|
140
|
+
issuer?: string | string[];
|
|
141
|
+
audience?: string | string[];
|
|
142
|
+
userIdClaim?: string;
|
|
143
|
+
algorithms?: string[];
|
|
144
|
+
clockTolerance?: number;
|
|
145
|
+
}
|
|
146
|
+
export interface SessionUserAuthConfig {
|
|
147
|
+
sessionSecret: string;
|
|
148
|
+
cookieName?: string;
|
|
149
|
+
algorithm?: 'sha256' | 'sha512';
|
|
150
|
+
}
|
|
151
|
+
export interface Credentials {
|
|
152
|
+
accessToken: string;
|
|
153
|
+
expiresAt?: number;
|
|
154
|
+
refreshToken?: string;
|
|
155
|
+
scope?: string;
|
|
156
|
+
tokenType?: string;
|
|
157
|
+
idToken?: string;
|
|
158
|
+
}
|
|
159
|
+
export type AuthFlowDescriptor = {
|
|
160
|
+
kind: 'credentials';
|
|
161
|
+
connection?: string;
|
|
162
|
+
provider?: string;
|
|
163
|
+
credentials: Credentials;
|
|
164
|
+
} | {
|
|
165
|
+
kind: 'auth_url';
|
|
166
|
+
connection?: string;
|
|
167
|
+
provider?: string;
|
|
168
|
+
url: string;
|
|
169
|
+
txn?: string;
|
|
170
|
+
state?: string;
|
|
171
|
+
codeVerifier?: string;
|
|
172
|
+
poll?: {
|
|
173
|
+
statusUrl: string;
|
|
174
|
+
interval?: number;
|
|
175
|
+
};
|
|
176
|
+
hint?: string;
|
|
177
|
+
} | {
|
|
178
|
+
kind: 'device_code';
|
|
179
|
+
connection?: string;
|
|
180
|
+
provider?: string;
|
|
181
|
+
txn?: string;
|
|
182
|
+
device: {
|
|
183
|
+
userCode: string;
|
|
184
|
+
verificationUri: string;
|
|
185
|
+
verificationUriComplete?: string;
|
|
186
|
+
expiresIn: number;
|
|
187
|
+
interval: number;
|
|
188
|
+
};
|
|
189
|
+
poll?: {
|
|
190
|
+
statusUrl: string;
|
|
191
|
+
interval?: number;
|
|
192
|
+
};
|
|
193
|
+
hint?: string;
|
|
194
|
+
} | {
|
|
195
|
+
kind: 'error';
|
|
196
|
+
error: string;
|
|
197
|
+
code?: number;
|
|
198
|
+
};
|
|
199
|
+
export declare class AuthRequiredError extends Error {
|
|
200
|
+
descriptor: AuthFlowDescriptor;
|
|
201
|
+
constructor(descriptor: AuthFlowDescriptor, message?: string);
|
|
202
|
+
}
|
|
203
|
+
export interface CachedToken {
|
|
204
|
+
accessToken: string;
|
|
205
|
+
refreshToken?: string;
|
|
206
|
+
expiresAt?: number;
|
|
207
|
+
scope?: string;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Tool config signature - explicit structural type mirroring SDK registerTool config
|
|
211
|
+
*
|
|
212
|
+
* Uses explicit structure instead of Parameters<> extraction to avoid TypeScript inference
|
|
213
|
+
* collapse to 'never' when using ToolModule[] arrays. The deep conditional types from
|
|
214
|
+
* Parameters<> cannot be unified across array elements.
|
|
215
|
+
*
|
|
216
|
+
* Validated against SDK signature for compatibility - compile errors if SDK changes.
|
|
217
|
+
*
|
|
218
|
+
* NOTE: This type is duplicated in @mcp-z/server for architectural independence.
|
|
219
|
+
* Keep these definitions synchronized manually when updating.
|
|
220
|
+
*/
|
|
221
|
+
export type ToolConfig = {
|
|
222
|
+
title?: string;
|
|
223
|
+
description?: string;
|
|
224
|
+
inputSchema?: ZodRawShapeCompat | AnySchema;
|
|
225
|
+
outputSchema?: ZodRawShapeCompat | AnySchema;
|
|
226
|
+
annotations?: ToolAnnotations;
|
|
227
|
+
_meta?: Record<string, unknown>;
|
|
228
|
+
};
|
|
229
|
+
/**
|
|
230
|
+
* Tool handler signature with generic support for middleware.
|
|
231
|
+
*
|
|
232
|
+
* @template TArgs - Tool arguments type (default: unknown for SDK compatibility)
|
|
233
|
+
* @template TExtra - Request handler extra type (default: RequestHandlerExtra from SDK)
|
|
234
|
+
*
|
|
235
|
+
* Defaults provide SDK-extracted types for compatibility with MCP SDK.
|
|
236
|
+
* Generic parameters enable type-safe middleware transformation.
|
|
237
|
+
*
|
|
238
|
+
* NOTE: This interface is duplicated in @mcp-z/server for architectural independence.
|
|
239
|
+
* Keep these definitions synchronized manually when updating.
|
|
240
|
+
*/
|
|
241
|
+
export type ToolHandler<TArgs = unknown, TExtra = RequestHandlerExtra<ServerRequest, ServerNotification>> = (args: TArgs, extra: TExtra) => Promise<CallToolResult>;
|
|
242
|
+
/**
|
|
243
|
+
* Tool module interface with bounded generics.
|
|
244
|
+
*
|
|
245
|
+
* @template TConfig - Tool config type (default: SDK ToolConfig)
|
|
246
|
+
* @template THandler - Handler function type (default: SDK ToolHandler)
|
|
247
|
+
*
|
|
248
|
+
* Use without generics for SDK-typed tools:
|
|
249
|
+
* - Business tool factories: `ToolModule`
|
|
250
|
+
* - Tool registration: `ToolModule[]`
|
|
251
|
+
*
|
|
252
|
+
* Use with generics for middleware transformation:
|
|
253
|
+
* - Auth middleware: `ToolModule<ToolConfig, ToolHandler<TArgs, EnrichedExtra>>`
|
|
254
|
+
*
|
|
255
|
+
* The bounds ensure compatibility with SDK registration.
|
|
256
|
+
*
|
|
257
|
+
* NOTE: This interface is duplicated in @mcp-z/server for architectural independence.
|
|
258
|
+
* Keep these definitions synchronized manually when updating.
|
|
259
|
+
*
|
|
260
|
+
* @see {@link ToolHandler} for handler function signature
|
|
261
|
+
* @see {@link AuthMiddlewareWrapper} for middleware wrapper pattern
|
|
262
|
+
*/
|
|
263
|
+
export interface ToolModule<TConfig = ToolConfig, THandler = unknown> {
|
|
264
|
+
name: string;
|
|
265
|
+
config: TConfig;
|
|
266
|
+
handler: THandler;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Middleware wrapper that enriches tool modules with authentication context.
|
|
270
|
+
*
|
|
271
|
+
* Wraps plain tool modules to inject authentication, logging, and request metadata.
|
|
272
|
+
* The wrapper pattern allows separation of business logic from cross-cutting concerns.
|
|
273
|
+
*
|
|
274
|
+
* @template TArgs - Tool arguments type (inferred from tool module)
|
|
275
|
+
* @template TExtra - Enriched extra type with auth context and logger
|
|
276
|
+
*
|
|
277
|
+
* @param toolModule - Plain tool module to wrap with auth middleware
|
|
278
|
+
* @returns Wrapped tool module with enriched handler signature
|
|
279
|
+
*
|
|
280
|
+
* @remarks
|
|
281
|
+
* Auth middleware wrappers typically:
|
|
282
|
+
* - Extract auth context from MCP request or OAuth provider
|
|
283
|
+
* - Inject logger instance for structured logging
|
|
284
|
+
* - Handle authentication errors with proper MCP error responses
|
|
285
|
+
* - Preserve tool configuration and metadata
|
|
286
|
+
*
|
|
287
|
+
* @example
|
|
288
|
+
* ```typescript
|
|
289
|
+
* // Actual usage pattern from OAuth providers (LoopbackOAuthProvider, ServiceAccountProvider, DcrOAuthProvider)
|
|
290
|
+
* const provider = new LoopbackOAuthProvider({ service: 'gmail', ... });
|
|
291
|
+
* const authMiddleware = provider.authMiddleware();
|
|
292
|
+
*
|
|
293
|
+
* // Apply middleware to tools (handlers receive enriched extra with authContext)
|
|
294
|
+
* const tools = toolFactories.map(f => f()).map(authMiddleware.withToolAuth);
|
|
295
|
+
* const resources = resourceFactories.map(f => f()).map(authMiddleware.withResourceAuth);
|
|
296
|
+
* const prompts = promptFactories.map(f => f()).map(authMiddleware.withPromptAuth);
|
|
297
|
+
*
|
|
298
|
+
* // Tool handler receives enriched extra with guaranteed authContext
|
|
299
|
+
* async function handler({ id }: In, extra: EnrichedExtra) {
|
|
300
|
+
* // extra.authContext.auth is OAuth2Client (from middleware)
|
|
301
|
+
* const gmail = google.gmail({ version: 'v1', auth: extra.authContext.auth });
|
|
302
|
+
* // ... business logic with authenticated context
|
|
303
|
+
* }
|
|
304
|
+
* ```
|
|
305
|
+
*
|
|
306
|
+
* @see {@link ToolModule} for base tool interface
|
|
307
|
+
* @see {@link ToolHandler} for handler function signature
|
|
308
|
+
*/
|
|
309
|
+
export type AuthMiddlewareWrapper<TArgs = unknown, TExtra = RequestHandlerExtra<ServerRequest, ServerNotification>> = (toolModule: ToolModule) => ToolModule<ToolConfig, ToolHandler<TArgs, TExtra>>;
|
|
310
|
+
/**
|
|
311
|
+
* Base interface for stateful OAuth adapters (LoopbackOAuthProvider pattern)
|
|
312
|
+
*
|
|
313
|
+
* Stateful adapters manage token storage, refresh, and multi-account state.
|
|
314
|
+
* Used for local development, test setup, and CI/CD workflows.
|
|
315
|
+
*
|
|
316
|
+
* Key characteristics:
|
|
317
|
+
* - Token storage and retrieval via tokenStore
|
|
318
|
+
* - Automatic token refresh with provider
|
|
319
|
+
* - Interactive OAuth flows (browser, ephemeral server)
|
|
320
|
+
* - Multi-account management
|
|
321
|
+
*
|
|
322
|
+
* Parameter usage:
|
|
323
|
+
* - accountId: Account identifier (email address for token storage)
|
|
324
|
+
*/
|
|
325
|
+
export interface OAuth2TokenStorageProvider {
|
|
326
|
+
/**
|
|
327
|
+
* Get access token for the specified account.
|
|
328
|
+
* If token is expired, automatically refreshes it.
|
|
329
|
+
* If token is missing, triggers OAuth flow (interactive) or throws AuthRequired (headless).
|
|
330
|
+
*
|
|
331
|
+
* @param accountId - Account identifier for multi-account support
|
|
332
|
+
* @returns Access token string
|
|
333
|
+
*/
|
|
334
|
+
getAccessToken(accountId?: string): Promise<string>;
|
|
335
|
+
/**
|
|
336
|
+
* Get email address for the specified account.
|
|
337
|
+
* Used during account registration to verify identity with provider.
|
|
338
|
+
*
|
|
339
|
+
* @param accountId - Account identifier
|
|
340
|
+
* @returns Email address from provider verification
|
|
341
|
+
*/
|
|
342
|
+
getUserEmail(accountId?: string): Promise<string>;
|
|
343
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for multi-account management and OAuth integration
|
|
3
|
+
*/ export class AccountManagerError extends Error {
|
|
4
|
+
constructor(message, code, retryable = false){
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'AccountManagerError';
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.retryable = retryable;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class AccountNotFoundError extends AccountManagerError {
|
|
12
|
+
constructor(accountRef){
|
|
13
|
+
super(`Account '${accountRef}' not found`, 'ACCOUNT_NOT_FOUND', false);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class ConfigurationError extends AccountManagerError {
|
|
17
|
+
constructor(message){
|
|
18
|
+
super(`Configuration error: ${message}`, 'CONFIGURATION_ERROR', false);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class RequiresAuthenticationError extends AccountManagerError {
|
|
22
|
+
constructor(service, accountId){
|
|
23
|
+
const message = accountId ? `No account found for ${service} (account: ${accountId}). Use account-add to connect one.` : `No account found for ${service}. Use account-add to connect one.`;
|
|
24
|
+
super(message, 'REQUIRES_AUTHENTICATION', false);
|
|
25
|
+
this.accountId = accountId;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export class AuthRequiredError extends Error {
|
|
29
|
+
constructor(descriptor, message){
|
|
30
|
+
super(message || `Authentication required: ${descriptor.kind}`);
|
|
31
|
+
this.name = 'AuthRequiredError';
|
|
32
|
+
this.descriptor = descriptor;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/oauth/oauth/src/types.ts"],"sourcesContent":["/**\n * Type definitions for multi-account management and OAuth integration\n */\n\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { AnySchema, ZodRawShapeCompat } from '@modelcontextprotocol/sdk/server/zod-compat.js';\nimport type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';\nimport type { CallToolResult, GetPromptResult, ServerNotification, ServerRequest, ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';\n\nexport type Logger = Pick<Console, 'info' | 'error' | 'warn' | 'debug'>;\n\nexport interface AccountInfo {\n email: string;\n alias?: string;\n addedAt: string;\n lastUsed?: string;\n metadata?: {\n name?: string;\n picture?: string;\n [key: string]: unknown;\n };\n}\n\n/**\n * MCP tool module definition with configuration and handler function.\n *\n * Represents a registered tool in the Model Context Protocol server that can be\n * invoked by MCP clients. Tools are the primary mechanism for executing operations\n * in response to client requests.\n *\n * @property name - Unique tool identifier (e.g., \"gmail-message-send\", \"sheets-values-get\")\n * @property config - Tool configuration including description and schemas\n * @property config.description - Human-readable description shown to MCP clients\n * @property config.inputSchema - Zod schema defining tool arguments (JSON-serializable)\n * @property config.outputSchema - Zod schema defining tool response structure\n * @property handler - Async function that executes the tool operation\n *\n * @remarks\n * This is the runtime representation of an MCP tool after registration. The handler\n * receives JSON-serializable arguments validated against inputSchema and returns\n * a CallToolResult validated against outputSchema.\n *\n * Tools are typically created using tool factory functions and registered with the\n * MCP server during initialization.\n *\n * @example\n * ```typescript\n * const tool: McpTool = {\n * name: \"gmail-message-send\",\n * config: {\n * description: \"Send an email message\",\n * inputSchema: { to: { type: \"string\" }, subject: { type: \"string\" } },\n * outputSchema: { result: { type: \"object\" } }\n * },\n * handler: async (args, context) => {\n * // Implementation\n * return { content: [{ type: \"text\", text: \"Message sent\" }] };\n * }\n * };\n * ```\n *\n * @see {@link McpPrompt} for prompt module definition\n */\nexport interface McpTool {\n name: string;\n config: {\n description: string;\n inputSchema: Record<string, unknown>;\n outputSchema: Record<string, unknown>;\n };\n handler: (args: unknown, context?: unknown) => Promise<CallToolResult>;\n}\n\n/**\n * MCP prompt module definition with configuration and handler function.\n *\n * Represents a registered prompt template in the Model Context Protocol server that\n * can be retrieved and rendered by MCP clients. Prompts provide reusable templates\n * for common interaction patterns.\n *\n * @property name - Unique prompt identifier (e.g., \"draft-email\", \"summarize-thread\")\n * @property config - Prompt configuration (schema and metadata are prompt-specific)\n * @property handler - Async function that generates the prompt content\n *\n * @remarks\n * This is the runtime representation of an MCP prompt after registration. Unlike\n * {@link McpTool} which executes operations, prompts generate templated content\n * that clients can use to structure interactions.\n *\n * The handler receives optional arguments and returns a GetPromptResult containing\n * the rendered prompt messages.\n *\n * @example\n * ```typescript\n * const prompt: McpPrompt = {\n * name: \"draft-email\",\n * config: {\n * description: \"Generate email draft from key points\",\n * arguments: [{ name: \"points\", description: \"Key points to include\" }]\n * },\n * handler: async (args) => {\n * const points = args?.points || [];\n * return {\n * messages: [{\n * role: \"user\",\n * content: { type: \"text\", text: `Draft email covering: ${points.join(\", \")}` }\n * }]\n * };\n * }\n * };\n * ```\n *\n * @see {@link McpTool} for tool module definition\n */\nexport interface McpPrompt {\n name: string;\n config: unknown;\n handler: (args: unknown) => Promise<GetPromptResult>;\n}\n\nexport class AccountManagerError extends Error {\n public code: string;\n public retryable: boolean;\n\n constructor(message: string, code: string, retryable = false) {\n super(message);\n this.name = 'AccountManagerError';\n this.code = code;\n this.retryable = retryable;\n }\n}\n\nexport class AccountNotFoundError extends AccountManagerError {\n constructor(accountRef: string) {\n super(`Account '${accountRef}' not found`, 'ACCOUNT_NOT_FOUND', false);\n }\n}\n\nexport class ConfigurationError extends AccountManagerError {\n constructor(message: string) {\n super(`Configuration error: ${message}`, 'CONFIGURATION_ERROR', false);\n }\n}\n\nexport class RequiresAuthenticationError extends AccountManagerError {\n public accountId: string | undefined;\n\n constructor(service: string, accountId?: string) {\n const message = accountId ? `No account found for ${service} (account: ${accountId}). Use account-add to connect one.` : `No account found for ${service}. Use account-add to connect one.`;\n super(message, 'REQUIRES_AUTHENTICATION', false);\n this.accountId = accountId;\n }\n}\n\nexport interface AuthEmailProvider {\n getUserEmail(accountId?: string): Promise<string>;\n authenticateNewAccount?(): Promise<string>;\n}\n\nexport interface UserAuthProvider {\n getUserId(req: unknown): Promise<string>; // Throws if auth invalid\n}\n\nexport interface JWTUserAuthConfig {\n secret?: string; // HS256 - MUST be at least 32 characters\n publicKey?: string | object; // RS256/ES256 - PEM string, JWK object, or JWKS URL\n jwksUrl?: string; // Alternative to publicKey\n issuer?: string | string[];\n audience?: string | string[];\n userIdClaim?: string; // Default: 'sub'\n algorithms?: string[]; // Default: auto-detect\n clockTolerance?: number; // Default: 0\n}\n\nexport interface SessionUserAuthConfig {\n sessionSecret: string; // MUST be at least 32 characters\n cookieName?: string; // Default: 'session'\n algorithm?: 'sha256' | 'sha512'; // Default: 'sha256'\n}\n\nexport interface Credentials {\n accessToken: string;\n expiresAt?: number;\n refreshToken?: string;\n scope?: string;\n tokenType?: string;\n idToken?: string;\n}\n\nexport type AuthFlowDescriptor =\n | { kind: 'credentials'; connection?: string; provider?: string; credentials: Credentials }\n | { kind: 'auth_url'; connection?: string; provider?: string; url: string; txn?: string; state?: string; codeVerifier?: string; poll?: { statusUrl: string; interval?: number }; hint?: string }\n | { kind: 'device_code'; connection?: string; provider?: string; txn?: string; device: { userCode: string; verificationUri: string; verificationUriComplete?: string; expiresIn: number; interval: number }; poll?: { statusUrl: string; interval?: number }; hint?: string }\n | { kind: 'error'; error: string; code?: number };\n\nexport class AuthRequiredError extends Error {\n public descriptor: AuthFlowDescriptor;\n\n constructor(descriptor: AuthFlowDescriptor, message?: string) {\n super(message || `Authentication required: ${descriptor.kind}`);\n this.name = 'AuthRequiredError';\n this.descriptor = descriptor;\n }\n}\n\nexport interface CachedToken {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n scope?: string;\n}\n\n/**\n * Tool config signature - explicit structural type mirroring SDK registerTool config\n *\n * Uses explicit structure instead of Parameters<> extraction to avoid TypeScript inference\n * collapse to 'never' when using ToolModule[] arrays. The deep conditional types from\n * Parameters<> cannot be unified across array elements.\n *\n * Validated against SDK signature for compatibility - compile errors if SDK changes.\n *\n * NOTE: This type is duplicated in @mcp-z/server for architectural independence.\n * Keep these definitions synchronized manually when updating.\n */\nexport type ToolConfig = {\n title?: string;\n description?: string;\n inputSchema?: ZodRawShapeCompat | AnySchema;\n outputSchema?: ZodRawShapeCompat | AnySchema;\n annotations?: ToolAnnotations;\n _meta?: Record<string, unknown>;\n};\n\n// Compile-time validation that ToolConfig is compatible with SDK\ntype _ValidateToolConfigAssignable = ToolConfig extends Parameters<McpServer['registerTool']>[1] ? true : never;\ntype _ValidateToolConfigReceivable = Parameters<McpServer['registerTool']>[1] extends ToolConfig ? true : never;\n\n/**\n * Tool handler signature with generic support for middleware.\n *\n * @template TArgs - Tool arguments type (default: unknown for SDK compatibility)\n * @template TExtra - Request handler extra type (default: RequestHandlerExtra from SDK)\n *\n * Defaults provide SDK-extracted types for compatibility with MCP SDK.\n * Generic parameters enable type-safe middleware transformation.\n *\n * NOTE: This interface is duplicated in @mcp-z/server for architectural independence.\n * Keep these definitions synchronized manually when updating.\n */\nexport type ToolHandler<TArgs = unknown, TExtra = RequestHandlerExtra<ServerRequest, ServerNotification>> = (args: TArgs, extra: TExtra) => Promise<CallToolResult>;\n\n/**\n * Tool module interface with bounded generics.\n *\n * @template TConfig - Tool config type (default: SDK ToolConfig)\n * @template THandler - Handler function type (default: SDK ToolHandler)\n *\n * Use without generics for SDK-typed tools:\n * - Business tool factories: `ToolModule`\n * - Tool registration: `ToolModule[]`\n *\n * Use with generics for middleware transformation:\n * - Auth middleware: `ToolModule<ToolConfig, ToolHandler<TArgs, EnrichedExtra>>`\n *\n * The bounds ensure compatibility with SDK registration.\n *\n * NOTE: This interface is duplicated in @mcp-z/server for architectural independence.\n * Keep these definitions synchronized manually when updating.\n *\n * @see {@link ToolHandler} for handler function signature\n * @see {@link AuthMiddlewareWrapper} for middleware wrapper pattern\n */\nexport interface ToolModule<TConfig = ToolConfig, THandler = unknown> {\n name: string;\n config: TConfig;\n handler: THandler;\n}\n\n/**\n * Middleware wrapper that enriches tool modules with authentication context.\n *\n * Wraps plain tool modules to inject authentication, logging, and request metadata.\n * The wrapper pattern allows separation of business logic from cross-cutting concerns.\n *\n * @template TArgs - Tool arguments type (inferred from tool module)\n * @template TExtra - Enriched extra type with auth context and logger\n *\n * @param toolModule - Plain tool module to wrap with auth middleware\n * @returns Wrapped tool module with enriched handler signature\n *\n * @remarks\n * Auth middleware wrappers typically:\n * - Extract auth context from MCP request or OAuth provider\n * - Inject logger instance for structured logging\n * - Handle authentication errors with proper MCP error responses\n * - Preserve tool configuration and metadata\n *\n * @example\n * ```typescript\n * // Actual usage pattern from OAuth providers (LoopbackOAuthProvider, ServiceAccountProvider, DcrOAuthProvider)\n * const provider = new LoopbackOAuthProvider({ service: 'gmail', ... });\n * const authMiddleware = provider.authMiddleware();\n *\n * // Apply middleware to tools (handlers receive enriched extra with authContext)\n * const tools = toolFactories.map(f => f()).map(authMiddleware.withToolAuth);\n * const resources = resourceFactories.map(f => f()).map(authMiddleware.withResourceAuth);\n * const prompts = promptFactories.map(f => f()).map(authMiddleware.withPromptAuth);\n *\n * // Tool handler receives enriched extra with guaranteed authContext\n * async function handler({ id }: In, extra: EnrichedExtra) {\n * // extra.authContext.auth is OAuth2Client (from middleware)\n * const gmail = google.gmail({ version: 'v1', auth: extra.authContext.auth });\n * // ... business logic with authenticated context\n * }\n * ```\n *\n * @see {@link ToolModule} for base tool interface\n * @see {@link ToolHandler} for handler function signature\n */\nexport type AuthMiddlewareWrapper<TArgs = unknown, TExtra = RequestHandlerExtra<ServerRequest, ServerNotification>> = (toolModule: ToolModule) => ToolModule<ToolConfig, ToolHandler<TArgs, TExtra>>;\n\n/**\n * Base interface for stateful OAuth adapters (LoopbackOAuthProvider pattern)\n *\n * Stateful adapters manage token storage, refresh, and multi-account state.\n * Used for local development, test setup, and CI/CD workflows.\n *\n * Key characteristics:\n * - Token storage and retrieval via tokenStore\n * - Automatic token refresh with provider\n * - Interactive OAuth flows (browser, ephemeral server)\n * - Multi-account management\n *\n * Parameter usage:\n * - accountId: Account identifier (email address for token storage)\n */\nexport interface OAuth2TokenStorageProvider {\n /**\n * Get access token for the specified account.\n * If token is expired, automatically refreshes it.\n * If token is missing, triggers OAuth flow (interactive) or throws AuthRequired (headless).\n *\n * @param accountId - Account identifier for multi-account support\n * @returns Access token string\n */\n getAccessToken(accountId?: string): Promise<string>;\n\n /**\n * Get email address for the specified account.\n * Used during account registration to verify identity with provider.\n *\n * @param accountId - Account identifier\n * @returns Email address from provider verification\n */\n getUserEmail(accountId?: string): Promise<string>;\n}\n"],"names":["AccountManagerError","Error","message","code","retryable","name","AccountNotFoundError","accountRef","ConfigurationError","RequiresAuthenticationError","service","accountId","AuthRequiredError","descriptor","kind"],"mappings":"AAAA;;CAEC,GAsHD,OAAO,MAAMA,4BAA4BC;IAIvC,YAAYC,OAAe,EAAEC,IAAY,EAAEC,YAAY,KAAK,CAAE;QAC5D,KAAK,CAACF;QACN,IAAI,CAACG,IAAI,GAAG;QACZ,IAAI,CAACF,IAAI,GAAGA;QACZ,IAAI,CAACC,SAAS,GAAGA;IACnB;AACF;AAEA,OAAO,MAAME,6BAA6BN;IACxC,YAAYO,UAAkB,CAAE;QAC9B,KAAK,CAAC,CAAC,SAAS,EAAEA,WAAW,WAAW,CAAC,EAAE,qBAAqB;IAClE;AACF;AAEA,OAAO,MAAMC,2BAA2BR;IACtC,YAAYE,OAAe,CAAE;QAC3B,KAAK,CAAC,CAAC,qBAAqB,EAAEA,SAAS,EAAE,uBAAuB;IAClE;AACF;AAEA,OAAO,MAAMO,oCAAoCT;IAG/C,YAAYU,OAAe,EAAEC,SAAkB,CAAE;QAC/C,MAAMT,UAAUS,YAAY,CAAC,qBAAqB,EAAED,QAAQ,WAAW,EAAEC,UAAU,kCAAkC,CAAC,GAAG,CAAC,qBAAqB,EAAED,QAAQ,iCAAiC,CAAC;QAC3L,KAAK,CAACR,SAAS,2BAA2B;QAC1C,IAAI,CAACS,SAAS,GAAGA;IACnB;AACF;AA2CA,OAAO,MAAMC,0BAA0BX;IAGrC,YAAYY,UAA8B,EAAEX,OAAgB,CAAE;QAC5D,KAAK,CAACA,WAAW,CAAC,yBAAyB,EAAEW,WAAWC,IAAI,EAAE;QAC9D,IAAI,CAACT,IAAI,GAAG;QACZ,IAAI,CAACQ,UAAU,GAAGA;IACpB;AACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mcp-z/oauth",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Multi-account orchestration and secure token storage for OAuth-based MCP servers",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"model-context-protocol",
|
|
8
|
+
"oauth",
|
|
9
|
+
"oauth2",
|
|
10
|
+
"authentication",
|
|
11
|
+
"multi-account",
|
|
12
|
+
"account-management",
|
|
13
|
+
"token-storage",
|
|
14
|
+
"secure-storage",
|
|
15
|
+
"keyv",
|
|
16
|
+
"mcp-server",
|
|
17
|
+
"oauth-google",
|
|
18
|
+
"oauth-microsoft",
|
|
19
|
+
"config-management",
|
|
20
|
+
"encryption",
|
|
21
|
+
"duckdb",
|
|
22
|
+
"ai",
|
|
23
|
+
"claude"
|
|
24
|
+
],
|
|
25
|
+
"homepage": "https://github.com/mcp-z/oauth#readme",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/mcp-z/oauth/issues"
|
|
28
|
+
},
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/mcp-z/oauth.git"
|
|
32
|
+
},
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"author": "Kevin Malakoff <kmalakoff.info@gmail.com>",
|
|
35
|
+
"type": "module",
|
|
36
|
+
"exports": {
|
|
37
|
+
".": {
|
|
38
|
+
"types": "./dist/esm/index.d.ts",
|
|
39
|
+
"import": "./dist/esm/index.js",
|
|
40
|
+
"require": "./dist/cjs/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./package.json": "./package.json"
|
|
43
|
+
},
|
|
44
|
+
"main": "./dist/cjs/index.js",
|
|
45
|
+
"module": "./dist/esm/index.js",
|
|
46
|
+
"types": "./dist/esm/index.d.ts",
|
|
47
|
+
"files": [
|
|
48
|
+
"dist"
|
|
49
|
+
],
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsds build",
|
|
52
|
+
"format": "tsds format",
|
|
53
|
+
"prepublish:check": "ncp",
|
|
54
|
+
"prepublishOnly": "tsds validate",
|
|
55
|
+
"test": "npm run test:unit && npm run test:integration",
|
|
56
|
+
"test:engines": "nvu engines tsds test:node --no-timeouts 'test/**/*.test.ts'",
|
|
57
|
+
"test:integration": "tsds test:node --no-timeouts 'test/integration/**/*.test.ts'",
|
|
58
|
+
"test:unit": "tsds test:node --no-timeouts 'test/unit/**/*.test.ts'",
|
|
59
|
+
"version": "tsds version"
|
|
60
|
+
},
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
63
|
+
"jose": "^6.1.3",
|
|
64
|
+
"keyv": "^5.5.5",
|
|
65
|
+
"keyv-file": "^5.3.3",
|
|
66
|
+
"zod": "^4.0.0"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@types/mocha": "^10.0.10",
|
|
70
|
+
"@types/node": "^25.0.2",
|
|
71
|
+
"node-version-use": "^2.1.6",
|
|
72
|
+
"ts-dev-stack": "^1.21.3",
|
|
73
|
+
"tsds-config": "^1.0.0",
|
|
74
|
+
"typescript": "^5.9.3"
|
|
75
|
+
},
|
|
76
|
+
"engines": {
|
|
77
|
+
"node": ">=24"
|
|
78
|
+
},
|
|
79
|
+
"tsds": {
|
|
80
|
+
"source": "src/index.ts"
|
|
81
|
+
}
|
|
82
|
+
}
|