@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.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +71 -0
  3. package/dist/cjs/account-utils.d.cts +107 -0
  4. package/dist/cjs/account-utils.d.ts +107 -0
  5. package/dist/cjs/account-utils.js +481 -0
  6. package/dist/cjs/account-utils.js.map +1 -0
  7. package/dist/cjs/index.d.cts +19 -0
  8. package/dist/cjs/index.d.ts +19 -0
  9. package/dist/cjs/index.js +149 -0
  10. package/dist/cjs/index.js.map +1 -0
  11. package/dist/cjs/jwt-auth.d.cts +53 -0
  12. package/dist/cjs/jwt-auth.d.ts +53 -0
  13. package/dist/cjs/jwt-auth.js +417 -0
  14. package/dist/cjs/jwt-auth.js.map +1 -0
  15. package/dist/cjs/key-utils.d.cts +131 -0
  16. package/dist/cjs/key-utils.d.ts +131 -0
  17. package/dist/cjs/key-utils.js +421 -0
  18. package/dist/cjs/key-utils.js.map +1 -0
  19. package/dist/cjs/lib/account-server/index.d.cts +45 -0
  20. package/dist/cjs/lib/account-server/index.d.ts +45 -0
  21. package/dist/cjs/lib/account-server/index.js +67 -0
  22. package/dist/cjs/lib/account-server/index.js.map +1 -0
  23. package/dist/cjs/lib/account-server/loopback.d.cts +22 -0
  24. package/dist/cjs/lib/account-server/loopback.d.ts +22 -0
  25. package/dist/cjs/lib/account-server/loopback.js +778 -0
  26. package/dist/cjs/lib/account-server/loopback.js.map +1 -0
  27. package/dist/cjs/lib/account-server/me.d.cts +23 -0
  28. package/dist/cjs/lib/account-server/me.d.ts +23 -0
  29. package/dist/cjs/lib/account-server/me.js +412 -0
  30. package/dist/cjs/lib/account-server/me.js.map +1 -0
  31. package/dist/cjs/lib/account-server/shared-utils.d.cts +6 -0
  32. package/dist/cjs/lib/account-server/shared-utils.d.ts +6 -0
  33. package/dist/cjs/lib/account-server/shared-utils.js +235 -0
  34. package/dist/cjs/lib/account-server/shared-utils.js.map +1 -0
  35. package/dist/cjs/lib/account-server/stateless.d.cts +20 -0
  36. package/dist/cjs/lib/account-server/stateless.d.ts +20 -0
  37. package/dist/cjs/lib/account-server/stateless.js +32 -0
  38. package/dist/cjs/lib/account-server/stateless.js.map +1 -0
  39. package/dist/cjs/lib/account-server/types.d.cts +32 -0
  40. package/dist/cjs/lib/account-server/types.d.ts +32 -0
  41. package/dist/cjs/lib/account-server/types.js +7 -0
  42. package/dist/cjs/lib/account-server/types.js.map +1 -0
  43. package/dist/cjs/lib/dcr-types.d.cts +126 -0
  44. package/dist/cjs/lib/dcr-types.d.ts +126 -0
  45. package/dist/cjs/lib/dcr-types.js +12 -0
  46. package/dist/cjs/lib/dcr-types.js.map +1 -0
  47. package/dist/cjs/lib/rfc-metadata-types.d.cts +46 -0
  48. package/dist/cjs/lib/rfc-metadata-types.d.ts +46 -0
  49. package/dist/cjs/lib/rfc-metadata-types.js +8 -0
  50. package/dist/cjs/lib/rfc-metadata-types.js.map +1 -0
  51. package/dist/cjs/package.json +1 -0
  52. package/dist/cjs/pkce.d.cts +36 -0
  53. package/dist/cjs/pkce.d.ts +36 -0
  54. package/dist/cjs/pkce.js +25 -0
  55. package/dist/cjs/pkce.js.map +1 -0
  56. package/dist/cjs/sanitizer.d.cts +37 -0
  57. package/dist/cjs/sanitizer.d.ts +37 -0
  58. package/dist/cjs/sanitizer.js +407 -0
  59. package/dist/cjs/sanitizer.js.map +1 -0
  60. package/dist/cjs/schemas/index.d.cts +36 -0
  61. package/dist/cjs/schemas/index.d.ts +36 -0
  62. package/dist/cjs/schemas/index.js +28 -0
  63. package/dist/cjs/schemas/index.js.map +1 -0
  64. package/dist/cjs/session-auth.d.cts +79 -0
  65. package/dist/cjs/session-auth.d.ts +79 -0
  66. package/dist/cjs/session-auth.js +354 -0
  67. package/dist/cjs/session-auth.js.map +1 -0
  68. package/dist/cjs/templates.d.cts +18 -0
  69. package/dist/cjs/templates.d.ts +18 -0
  70. package/dist/cjs/templates.js +38 -0
  71. package/dist/cjs/templates.js.map +1 -0
  72. package/dist/cjs/types.d.cts +343 -0
  73. package/dist/cjs/types.d.ts +343 -0
  74. package/dist/cjs/types.js +210 -0
  75. package/dist/cjs/types.js.map +1 -0
  76. package/dist/esm/account-utils.d.ts +107 -0
  77. package/dist/esm/account-utils.js +179 -0
  78. package/dist/esm/account-utils.js.map +1 -0
  79. package/dist/esm/index.d.ts +19 -0
  80. package/dist/esm/index.js +23 -0
  81. package/dist/esm/index.js.map +1 -0
  82. package/dist/esm/jwt-auth.d.ts +53 -0
  83. package/dist/esm/jwt-auth.js +164 -0
  84. package/dist/esm/jwt-auth.js.map +1 -0
  85. package/dist/esm/key-utils.d.ts +131 -0
  86. package/dist/esm/key-utils.js +143 -0
  87. package/dist/esm/key-utils.js.map +1 -0
  88. package/dist/esm/lib/account-server/index.d.ts +45 -0
  89. package/dist/esm/lib/account-server/index.js +41 -0
  90. package/dist/esm/lib/account-server/index.js.map +1 -0
  91. package/dist/esm/lib/account-server/loopback.d.ts +22 -0
  92. package/dist/esm/lib/account-server/loopback.js +372 -0
  93. package/dist/esm/lib/account-server/loopback.js.map +1 -0
  94. package/dist/esm/lib/account-server/me.d.ts +23 -0
  95. package/dist/esm/lib/account-server/me.js +170 -0
  96. package/dist/esm/lib/account-server/me.js.map +1 -0
  97. package/dist/esm/lib/account-server/shared-utils.d.ts +6 -0
  98. package/dist/esm/lib/account-server/shared-utils.js +24 -0
  99. package/dist/esm/lib/account-server/shared-utils.js.map +1 -0
  100. package/dist/esm/lib/account-server/stateless.d.ts +20 -0
  101. package/dist/esm/lib/account-server/stateless.js +25 -0
  102. package/dist/esm/lib/account-server/stateless.js.map +1 -0
  103. package/dist/esm/lib/account-server/types.d.ts +32 -0
  104. package/dist/esm/lib/account-server/types.js +6 -0
  105. package/dist/esm/lib/account-server/types.js.map +1 -0
  106. package/dist/esm/lib/dcr-types.d.ts +126 -0
  107. package/dist/esm/lib/dcr-types.js +13 -0
  108. package/dist/esm/lib/dcr-types.js.map +1 -0
  109. package/dist/esm/lib/rfc-metadata-types.d.ts +46 -0
  110. package/dist/esm/lib/rfc-metadata-types.js +7 -0
  111. package/dist/esm/lib/rfc-metadata-types.js.map +1 -0
  112. package/dist/esm/package.json +1 -0
  113. package/dist/esm/pkce.d.ts +36 -0
  114. package/dist/esm/pkce.js +33 -0
  115. package/dist/esm/pkce.js.map +1 -0
  116. package/dist/esm/sanitizer.d.ts +37 -0
  117. package/dist/esm/sanitizer.js +256 -0
  118. package/dist/esm/sanitizer.js.map +1 -0
  119. package/dist/esm/schemas/index.d.ts +36 -0
  120. package/dist/esm/schemas/index.js +19 -0
  121. package/dist/esm/schemas/index.js.map +1 -0
  122. package/dist/esm/session-auth.d.ts +79 -0
  123. package/dist/esm/session-auth.js +141 -0
  124. package/dist/esm/session-auth.js.map +1 -0
  125. package/dist/esm/templates.d.ts +18 -0
  126. package/dist/esm/templates.js +132 -0
  127. package/dist/esm/templates.js.map +1 -0
  128. package/dist/esm/types.d.ts +343 -0
  129. package/dist/esm/types.js +34 -0
  130. package/dist/esm/types.js.map +1 -0
  131. package/package.json +82 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/oauth/oauth/src/lib/account-server/loopback.ts"],"sourcesContent":["/**\n * Loopback OAuth account management tools.\n *\n * Provides account management for LoopbackOAuthProvider (server-managed multi-account).\n * Users can add multiple accounts, switch between them, and manage identities.\n *\n * Tools:\n * - account-me: Show current user identity (email, alias, session expiry)\n * - account-switch: Use account (add if needed, switch if already linked)\n * - account-remove: Remove account and delete tokens\n * - account-list: Show all linked accounts (returns empty array if none)\n */\n\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';\nimport { z } from 'zod';\nimport { addAccount, getAccountInfo, getActiveAccount, getLinkedAccounts, removeAccount, setAccountInfo, setActiveAccount } from '../../account-utils.ts';\nimport type { AccountInfo, McpPrompt, McpTool } from '../../types.ts';\nimport { createAccountMe } from './me.ts';\nimport { findAccountByEmailOrAlias } from './shared-utils.ts';\nimport type { AccountLoopbackConfig } from './types.ts';\n\n/**\n * Create loopback OAuth account management tools.\n * Returns 4 tools: account-me, account-switch, account-remove, account-list.\n */\nexport function createLoopback(config: AccountLoopbackConfig): { tools: McpTool[]; prompts: McpPrompt[] } {\n const { service, store, logger, auth } = config;\n\n // Create account-me tool\n const meTools = createAccountMe({ service, store, logger, mode: 'loopback' });\n\n const tools: McpTool[] = [\n ...meTools.tools,\n // account-switch\n {\n name: 'account-switch',\n config: {\n description: `Use ${service} account (smart mode). If email/alias provided and already linked, switches to it without triggering OAuth. If not linked or no email provided, triggers OAuth browser flow to add account. Returns account email, whether it was newly added, and total account count.`,\n inputSchema: {\n email: z.string().optional().describe('Email address to link (if already linked, switches without OAuth)'),\n alias: z.string().optional().describe('Optional alias for easy identification'),\n } as const,\n outputSchema: {\n result: z.discriminatedUnion('type', [\n z.object({\n type: z.literal('success'),\n email: z.string(),\n isNew: z.boolean(),\n totalAccounts: z.number(),\n message: z.string(),\n }),\n ]),\n } as const,\n },\n handler: async (args: unknown): Promise<CallToolResult> => {\n const params = args as { email?: string; alias?: string };\n try {\n logger.info(`Starting account switch for ${service}`, { email: params.email, alias: params.alias });\n\n // Get existing accounts\n const existingAccounts = await getLinkedAccounts(store, { service });\n\n let email: string;\n let isNew: boolean;\n\n // Smart behavior: check if email provided and already linked\n if (params.email) {\n // Find account by email or alias\n const accountId = await findAccountByEmailOrAlias(store, service, params.email);\n\n if (accountId) {\n // Account already linked - just switch to it\n email = accountId;\n isNew = false;\n logger.info(`Account already linked: ${email}, switching without OAuth`);\n\n // Set as active account\n await setActiveAccount(store, { service, accountId: email });\n\n // Update alias if provided\n if (params.alias) {\n const existingInfo = await getAccountInfo(store, { accountId: email, service });\n const accountInfo: AccountInfo = {\n email,\n alias: params.alias,\n addedAt: existingInfo?.addedAt ?? new Date().toISOString(),\n };\n await setAccountInfo(store, { accountId: email, service }, accountInfo);\n }\n\n const result = {\n type: 'success' as const,\n email,\n isNew: false,\n totalAccounts: existingAccounts.length,\n message: `Account already linked: ${email}. Set as active account (no OAuth needed).`,\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],\n structuredContent: { result },\n };\n }\n }\n\n // Not linked or no email provided - trigger OAuth flow for new account\n // Check if provider supports interactive authentication\n if (!auth.authenticateNewAccount) {\n throw new Error('Account switching requires interactive authentication. ' + 'The current auth provider does not support authenticateNewAccount().');\n }\n\n // Trigger new authentication with account selection\n email = await auth.authenticateNewAccount();\n\n // Check if account already exists (in case OAuth returned different email than requested)\n isNew = !existingAccounts.includes(email);\n\n if (isNew) {\n // Add new account\n await addAccount(store, { service, accountId: email });\n logger.info(`Added new ${service} account`, { email });\n } else {\n logger.info(`Account already linked: ${email}`);\n }\n\n // Set/update account info\n const existingInfo = await getAccountInfo(store, { accountId: email, service });\n const accountInfo: AccountInfo = {\n email,\n ...(params.alias ? { alias: params.alias } : {}),\n addedAt: isNew ? new Date().toISOString() : (existingInfo?.addedAt ?? new Date().toISOString()),\n };\n await setAccountInfo(store, { accountId: email, service }, accountInfo);\n\n // Set as active account\n await setActiveAccount(store, { service, accountId: email });\n\n const totalAccounts = isNew ? existingAccounts.length + 1 : existingAccounts.length;\n\n const result = {\n type: 'success' as const,\n email,\n isNew,\n totalAccounts,\n message: isNew ? `Successfully added ${service} account: ${email} (${totalAccounts} total)` : `Account already linked: ${email}. Set as active account.`,\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],\n structuredContent: { result },\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new McpError(ErrorCode.InternalError, `Error switching ${service} account: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n },\n },\n\n // account-remove\n {\n name: 'account-remove',\n config: {\n description: `Remove ${service} account and delete stored tokens permanently. If removing the active account, the first remaining account becomes active. Requires email or alias parameter.`,\n inputSchema: {\n accountId: z.string().min(1).describe('Email address or alias of account to remove'),\n } as const,\n outputSchema: {\n result: z.discriminatedUnion('type', [\n z.object({\n type: z.literal('success'),\n service: z.string(),\n removed: z.string(),\n remainingAccounts: z.number(),\n newActiveAccount: z.string().optional(),\n message: z.string(),\n }),\n ]),\n } as const,\n },\n handler: async (args: unknown): Promise<CallToolResult> => {\n const params = args as { accountId: string };\n try {\n const linkedAccounts = await getLinkedAccounts(store, { service });\n if (linkedAccounts.length === 0) {\n throw new Error(`No ${service} accounts to remove`);\n }\n\n // Find account by email or alias\n const accountId = await findAccountByEmailOrAlias(store, service, params.accountId);\n\n if (!accountId) {\n throw new Error(`Account not found: ${params.accountId}`);\n }\n\n // Get current active account\n const activeAccount = await getActiveAccount(store, { service });\n const removingActive = activeAccount === accountId;\n\n // Remove the account\n await removeAccount(store, { service, accountId });\n const remainingAccounts = linkedAccounts.filter((id) => id !== accountId);\n\n // If we removed the active account, set first remaining as active\n let newActiveAccount: string | undefined;\n if (removingActive && remainingAccounts.length > 0) {\n const firstRemaining = remainingAccounts[0];\n if (firstRemaining) {\n newActiveAccount = firstRemaining;\n await setActiveAccount(store, { service, accountId: newActiveAccount });\n }\n }\n\n logger.info(`Successfully removed ${service} account`, { accountId, remainingAccounts: remainingAccounts.length });\n\n const result = {\n type: 'success' as const,\n service,\n removed: accountId,\n remainingAccounts: remainingAccounts.length,\n ...(newActiveAccount && { newActiveAccount }),\n message: `Removed ${service} account: ${accountId}${newActiveAccount ? `. Active account is now: ${newActiveAccount}` : ''}`,\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],\n structuredContent: { result },\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new McpError(ErrorCode.InternalError, `Error removing ${service} account: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n },\n },\n\n // account-list\n {\n name: 'account-list',\n config: {\n description: `List all linked ${service} accounts with their aliases and active status.`,\n inputSchema: {} as const,\n outputSchema: {\n result: z.discriminatedUnion('type', [\n z.object({\n type: z.literal('success'),\n service: z.string(),\n accounts: z.array(\n z.object({\n email: z.string(),\n alias: z.string().optional(),\n isActive: z.boolean(),\n })\n ),\n totalAccounts: z.number(),\n message: z.string(),\n }),\n ]),\n } as const,\n },\n handler: async (): Promise<CallToolResult> => {\n try {\n const linkedAccounts = await getLinkedAccounts(store, { service });\n\n // Return empty array gracefully (no error when no accounts)\n if (linkedAccounts.length === 0) {\n const result = {\n type: 'success' as const,\n service,\n accounts: [],\n totalAccounts: 0,\n message: `No ${service} accounts linked. Use account-switch to add an account.`,\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],\n structuredContent: { result },\n };\n }\n\n const activeAccountId = await getActiveAccount(store, { service });\n\n // Get account info for each linked account\n const accounts = await Promise.all(\n linkedAccounts.map(async (email) => {\n const accountInfo = await getAccountInfo(store, { accountId: email, service });\n return {\n email,\n alias: accountInfo?.alias,\n isActive: email === activeAccountId,\n };\n })\n );\n\n const result = {\n type: 'success' as const,\n service,\n accounts,\n totalAccounts: linkedAccounts.length,\n message: `Found ${linkedAccounts.length} ${service} account(s)`,\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],\n structuredContent: { result },\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new McpError(ErrorCode.InternalError, `Error listing ${service} accounts: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n },\n },\n ];\n\n const prompts: McpPrompt[] = [];\n\n return { tools, prompts };\n}\n"],"names":["createLoopback","config","service","store","logger","auth","meTools","createAccountMe","mode","tools","name","description","inputSchema","email","z","string","optional","describe","alias","outputSchema","result","discriminatedUnion","object","type","literal","isNew","boolean","totalAccounts","number","message","handler","args","params","existingAccounts","accountId","existingInfo","accountInfo","error","info","getLinkedAccounts","findAccountByEmailOrAlias","setActiveAccount","getAccountInfo","addedAt","Date","toISOString","setAccountInfo","length","content","text","JSON","stringify","structuredContent","authenticateNewAccount","Error","includes","addAccount","String","McpError","ErrorCode","InternalError","stack","undefined","min","removed","remainingAccounts","newActiveAccount","linkedAccounts","activeAccount","removingActive","firstRemaining","getActiveAccount","removeAccount","filter","id","accounts","array","isActive","activeAccountId","Promise","all","map","prompts"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Account "me" tool - Who am I currently authenticated as?
3
+ *
4
+ * Provides current user identity across all auth modes:
5
+ * - Loopback: email, alias, sessionExpiresIn from stored tokens
6
+ * - DCR/Stateless: email from bearer token context, sessionExpiresIn=null
7
+ * - Device Code: email, sessionExpiresIn from stored tokens
8
+ * - Service Account: email, sessionExpiresIn="never" (JWT-based)
9
+ *
10
+ * Tool: {service}-account-me
11
+ */
12
+ import type { McpPrompt, McpTool } from '../../types.js';
13
+ import type { AccountMeConfig } from './types.js';
14
+ /**
15
+ * Create account-me tool for current user identity.
16
+ *
17
+ * Returns email, optional alias (loopback only), and session expiry info.
18
+ * Throws error if no active account in loopback mode.
19
+ */
20
+ export declare function createAccountMe(config: AccountMeConfig): {
21
+ tools: McpTool[];
22
+ prompts: McpPrompt[];
23
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Account "me" tool - Who am I currently authenticated as?
3
+ *
4
+ * Provides current user identity across all auth modes:
5
+ * - Loopback: email, alias, sessionExpiresIn from stored tokens
6
+ * - DCR/Stateless: email from bearer token context, sessionExpiresIn=null
7
+ * - Device Code: email, sessionExpiresIn from stored tokens
8
+ * - Service Account: email, sessionExpiresIn="never" (JWT-based)
9
+ *
10
+ * Tool: {service}-account-me
11
+ */
12
+ import type { McpPrompt, McpTool } from '../../types.js';
13
+ import type { AccountMeConfig } from './types.js';
14
+ /**
15
+ * Create account-me tool for current user identity.
16
+ *
17
+ * Returns email, optional alias (loopback only), and session expiry info.
18
+ * Throws error if no active account in loopback mode.
19
+ */
20
+ export declare function createAccountMe(config: AccountMeConfig): {
21
+ tools: McpTool[];
22
+ prompts: McpPrompt[];
23
+ };
@@ -0,0 +1,412 @@
1
+ /**
2
+ * Account "me" tool - Who am I currently authenticated as?
3
+ *
4
+ * Provides current user identity across all auth modes:
5
+ * - Loopback: email, alias, sessionExpiresIn from stored tokens
6
+ * - DCR/Stateless: email from bearer token context, sessionExpiresIn=null
7
+ * - Device Code: email, sessionExpiresIn from stored tokens
8
+ * - Service Account: email, sessionExpiresIn="never" (JWT-based)
9
+ *
10
+ * Tool: {service}-account-me
11
+ */ "use strict";
12
+ Object.defineProperty(exports, "__esModule", {
13
+ value: true
14
+ });
15
+ Object.defineProperty(exports, "createAccountMe", {
16
+ enumerable: true,
17
+ get: function() {
18
+ return createAccountMe;
19
+ }
20
+ });
21
+ var _types = require("@modelcontextprotocol/sdk/types.js");
22
+ var _zod = require("zod");
23
+ var _accountutilsts = require("../../account-utils.js");
24
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
25
+ try {
26
+ var info = gen[key](arg);
27
+ var value = info.value;
28
+ } catch (error) {
29
+ reject(error);
30
+ return;
31
+ }
32
+ if (info.done) {
33
+ resolve(value);
34
+ } else {
35
+ Promise.resolve(value).then(_next, _throw);
36
+ }
37
+ }
38
+ function _async_to_generator(fn) {
39
+ return function() {
40
+ var self = this, args = arguments;
41
+ return new Promise(function(resolve, reject) {
42
+ var gen = fn.apply(self, args);
43
+ function _next(value) {
44
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
45
+ }
46
+ function _throw(err) {
47
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
48
+ }
49
+ _next(undefined);
50
+ });
51
+ };
52
+ }
53
+ function _define_property(obj, key, value) {
54
+ if (key in obj) {
55
+ Object.defineProperty(obj, key, {
56
+ value: value,
57
+ enumerable: true,
58
+ configurable: true,
59
+ writable: true
60
+ });
61
+ } else {
62
+ obj[key] = value;
63
+ }
64
+ return obj;
65
+ }
66
+ function _instanceof(left, right) {
67
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
68
+ return !!right[Symbol.hasInstance](left);
69
+ } else {
70
+ return left instanceof right;
71
+ }
72
+ }
73
+ function _object_spread(target) {
74
+ for(var i = 1; i < arguments.length; i++){
75
+ var source = arguments[i] != null ? arguments[i] : {};
76
+ var ownKeys = Object.keys(source);
77
+ if (typeof Object.getOwnPropertySymbols === "function") {
78
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
79
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
80
+ }));
81
+ }
82
+ ownKeys.forEach(function(key) {
83
+ _define_property(target, key, source[key]);
84
+ });
85
+ }
86
+ return target;
87
+ }
88
+ function ownKeys(object, enumerableOnly) {
89
+ var keys = Object.keys(object);
90
+ if (Object.getOwnPropertySymbols) {
91
+ var symbols = Object.getOwnPropertySymbols(object);
92
+ if (enumerableOnly) {
93
+ symbols = symbols.filter(function(sym) {
94
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
95
+ });
96
+ }
97
+ keys.push.apply(keys, symbols);
98
+ }
99
+ return keys;
100
+ }
101
+ function _object_spread_props(target, source) {
102
+ source = source != null ? source : {};
103
+ if (Object.getOwnPropertyDescriptors) {
104
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
105
+ } else {
106
+ ownKeys(Object(source)).forEach(function(key) {
107
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
108
+ });
109
+ }
110
+ return target;
111
+ }
112
+ function _ts_generator(thisArg, body) {
113
+ var f, y, t, _ = {
114
+ label: 0,
115
+ sent: function() {
116
+ if (t[0] & 1) throw t[1];
117
+ return t[1];
118
+ },
119
+ trys: [],
120
+ ops: []
121
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
122
+ return d(g, "next", {
123
+ value: verb(0)
124
+ }), d(g, "throw", {
125
+ value: verb(1)
126
+ }), d(g, "return", {
127
+ value: verb(2)
128
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
129
+ value: function() {
130
+ return this;
131
+ }
132
+ }), g;
133
+ function verb(n) {
134
+ return function(v) {
135
+ return step([
136
+ n,
137
+ v
138
+ ]);
139
+ };
140
+ }
141
+ function step(op) {
142
+ if (f) throw new TypeError("Generator is already executing.");
143
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
144
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
145
+ if (y = 0, t) op = [
146
+ op[0] & 2,
147
+ t.value
148
+ ];
149
+ switch(op[0]){
150
+ case 0:
151
+ case 1:
152
+ t = op;
153
+ break;
154
+ case 4:
155
+ _.label++;
156
+ return {
157
+ value: op[1],
158
+ done: false
159
+ };
160
+ case 5:
161
+ _.label++;
162
+ y = op[1];
163
+ op = [
164
+ 0
165
+ ];
166
+ continue;
167
+ case 7:
168
+ op = _.ops.pop();
169
+ _.trys.pop();
170
+ continue;
171
+ default:
172
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
173
+ _ = 0;
174
+ continue;
175
+ }
176
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
177
+ _.label = op[1];
178
+ break;
179
+ }
180
+ if (op[0] === 6 && _.label < t[1]) {
181
+ _.label = t[1];
182
+ t = op;
183
+ break;
184
+ }
185
+ if (t && _.label < t[2]) {
186
+ _.label = t[2];
187
+ _.ops.push(op);
188
+ break;
189
+ }
190
+ if (t[2]) _.ops.pop();
191
+ _.trys.pop();
192
+ continue;
193
+ }
194
+ op = body.call(thisArg, _);
195
+ } catch (e) {
196
+ op = [
197
+ 6,
198
+ e
199
+ ];
200
+ y = 0;
201
+ } finally{
202
+ f = t = 0;
203
+ }
204
+ if (op[0] & 5) throw op[1];
205
+ return {
206
+ value: op[0] ? op[1] : void 0,
207
+ done: true
208
+ };
209
+ }
210
+ }
211
+ /**
212
+ * Format milliseconds as human-readable duration
213
+ * Examples: "2h 15m", "45m", "30s"
214
+ */ function formatDuration(ms) {
215
+ var totalSeconds = Math.floor(ms / 1000);
216
+ if (totalSeconds < 60) {
217
+ return "".concat(totalSeconds, "s");
218
+ }
219
+ var minutes = Math.floor(totalSeconds / 60);
220
+ if (minutes < 60) {
221
+ return "".concat(minutes, "m");
222
+ }
223
+ var hours = Math.floor(minutes / 60);
224
+ var remainingMinutes = minutes % 60;
225
+ if (remainingMinutes === 0) {
226
+ return "".concat(hours, "h");
227
+ }
228
+ return "".concat(hours, "h ").concat(remainingMinutes, "m");
229
+ }
230
+ function createAccountMe(config) {
231
+ var service = config.service, store = config.store, logger = config.logger, mode = config.mode;
232
+ var tools = [
233
+ {
234
+ name: 'account-me',
235
+ config: {
236
+ description: "Show current ".concat(service, " user identity. Returns email, alias (if set), and session expiry information."),
237
+ inputSchema: {},
238
+ outputSchema: {
239
+ result: _zod.z.discriminatedUnion('type', [
240
+ _zod.z.object({
241
+ type: _zod.z.literal('success'),
242
+ service: _zod.z.string(),
243
+ email: _zod.z.string(),
244
+ alias: _zod.z.string().optional(),
245
+ sessionExpiresIn: _zod.z.string().nullable().optional(),
246
+ message: _zod.z.string()
247
+ })
248
+ ])
249
+ }
250
+ },
251
+ handler: function(_args, extra) {
252
+ return _async_to_generator(function() {
253
+ var _ref, authContext, result, activeAccountId, accountInfo, email, alias, sessionExpiresIn, token, now, unused, result1, error, _logger_error, message;
254
+ return _ts_generator(this, function(_state) {
255
+ switch(_state.label){
256
+ case 0:
257
+ _state.trys.push([
258
+ 0,
259
+ 7,
260
+ ,
261
+ 8
262
+ ]);
263
+ // Mode-specific implementation
264
+ if (mode === 'stateless') {
265
+ // DCR/Stateless: Extract email from auth context
266
+ authContext = extra === null || extra === void 0 ? void 0 : extra.authContext;
267
+ if (!(authContext === null || authContext === void 0 ? void 0 : authContext.accountId)) {
268
+ throw new Error('No authentication context available. DCR mode requires bearer token.');
269
+ }
270
+ result = {
271
+ type: 'success',
272
+ service: service,
273
+ email: authContext.accountId,
274
+ sessionExpiresIn: null,
275
+ message: "Authenticated as ".concat(authContext.accountId, ". Session managed by MCP client.")
276
+ };
277
+ return [
278
+ 2,
279
+ {
280
+ content: [
281
+ {
282
+ type: 'text',
283
+ text: JSON.stringify(result, null, 2)
284
+ }
285
+ ],
286
+ structuredContent: {
287
+ result: result
288
+ }
289
+ }
290
+ ];
291
+ }
292
+ // Loopback/Device Code/Service Account: Use store
293
+ if (!store) {
294
+ throw new Error('Store is required for non-stateless mode');
295
+ }
296
+ return [
297
+ 4,
298
+ (0, _accountutilsts.getActiveAccount)(store, {
299
+ service: service
300
+ })
301
+ ];
302
+ case 1:
303
+ activeAccountId = _state.sent();
304
+ if (!activeAccountId) {
305
+ throw new Error("No active ".concat(service, " account found. Use account-switch to add an account."));
306
+ }
307
+ return [
308
+ 4,
309
+ (0, _accountutilsts.getAccountInfo)(store, {
310
+ accountId: activeAccountId,
311
+ service: service
312
+ })
313
+ ];
314
+ case 2:
315
+ accountInfo = _state.sent();
316
+ email = (_ref = accountInfo === null || accountInfo === void 0 ? void 0 : accountInfo.email) !== null && _ref !== void 0 ? _ref : activeAccountId;
317
+ alias = accountInfo === null || accountInfo === void 0 ? void 0 : accountInfo.alias;
318
+ // Calculate session expiry
319
+ sessionExpiresIn = null;
320
+ _state.label = 3;
321
+ case 3:
322
+ _state.trys.push([
323
+ 3,
324
+ 5,
325
+ ,
326
+ 6
327
+ ]);
328
+ return [
329
+ 4,
330
+ (0, _accountutilsts.getToken)(store, {
331
+ accountId: activeAccountId,
332
+ service: service
333
+ })
334
+ ];
335
+ case 4:
336
+ token = _state.sent();
337
+ if (token === null || token === void 0 ? void 0 : token.expiresAt) {
338
+ now = Date.now();
339
+ if (token.expiresAt > now) {
340
+ sessionExpiresIn = formatDuration(token.expiresAt - now);
341
+ } else {
342
+ sessionExpiresIn = 'expired';
343
+ }
344
+ } else {
345
+ // No expiry = JWT-based service account or no token info
346
+ sessionExpiresIn = 'never';
347
+ }
348
+ return [
349
+ 3,
350
+ 6
351
+ ];
352
+ case 5:
353
+ unused = _state.sent();
354
+ // Token not found or error reading - treat as "never" (service account pattern)
355
+ sessionExpiresIn = 'never';
356
+ return [
357
+ 3,
358
+ 6
359
+ ];
360
+ case 6:
361
+ result1 = _object_spread_props(_object_spread({
362
+ type: 'success',
363
+ service: service,
364
+ email: email
365
+ }, alias && {
366
+ alias: alias
367
+ }, sessionExpiresIn && {
368
+ sessionExpiresIn: sessionExpiresIn
369
+ }), {
370
+ message: "Authenticated as ".concat(email).concat(alias ? " (".concat(alias, ")") : '').concat(sessionExpiresIn ? ". Session expires in ".concat(sessionExpiresIn) : '', ".")
371
+ });
372
+ return [
373
+ 2,
374
+ {
375
+ content: [
376
+ {
377
+ type: 'text',
378
+ text: JSON.stringify(result1, null, 2)
379
+ }
380
+ ],
381
+ structuredContent: {
382
+ result: result1
383
+ }
384
+ }
385
+ ];
386
+ case 7:
387
+ error = _state.sent();
388
+ message = _instanceof(error, Error) ? error.message : String(error);
389
+ logger === null || logger === void 0 ? void 0 : (_logger_error = logger.error) === null || _logger_error === void 0 ? void 0 : _logger_error.call(logger, 'account-me.error', {
390
+ service: service,
391
+ error: message
392
+ });
393
+ throw new _types.McpError(_types.ErrorCode.InternalError, "Error getting ".concat(service, " account info: ").concat(message), {
394
+ stack: _instanceof(error, Error) ? error.stack : undefined
395
+ });
396
+ case 8:
397
+ return [
398
+ 2
399
+ ];
400
+ }
401
+ });
402
+ })();
403
+ }
404
+ }
405
+ ];
406
+ var prompts = [];
407
+ return {
408
+ tools: tools,
409
+ prompts: prompts
410
+ };
411
+ }
412
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/oauth/oauth/src/lib/account-server/me.ts"],"sourcesContent":["/**\n * Account \"me\" tool - Who am I currently authenticated as?\n *\n * Provides current user identity across all auth modes:\n * - Loopback: email, alias, sessionExpiresIn from stored tokens\n * - DCR/Stateless: email from bearer token context, sessionExpiresIn=null\n * - Device Code: email, sessionExpiresIn from stored tokens\n * - Service Account: email, sessionExpiresIn=\"never\" (JWT-based)\n *\n * Tool: {service}-account-me\n */\n\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';\nimport { z } from 'zod';\nimport { getAccountInfo, getActiveAccount, getToken } from '../../account-utils.ts';\nimport type { CachedToken, McpPrompt, McpTool } from '../../types.ts';\nimport type { AccountMeConfig } from './types.ts';\n\n/**\n * Format milliseconds as human-readable duration\n * Examples: \"2h 15m\", \"45m\", \"30s\"\n */\nfunction formatDuration(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000);\n\n if (totalSeconds < 60) {\n return `${totalSeconds}s`;\n }\n\n const minutes = Math.floor(totalSeconds / 60);\n if (minutes < 60) {\n return `${minutes}m`;\n }\n\n const hours = Math.floor(minutes / 60);\n const remainingMinutes = minutes % 60;\n\n if (remainingMinutes === 0) {\n return `${hours}h`;\n }\n\n return `${hours}h ${remainingMinutes}m`;\n}\n\n/**\n * Create account-me tool for current user identity.\n *\n * Returns email, optional alias (loopback only), and session expiry info.\n * Throws error if no active account in loopback mode.\n */\nexport function createAccountMe(config: AccountMeConfig): { tools: McpTool[]; prompts: McpPrompt[] } {\n const { service, store, logger, mode } = config;\n\n const tools: McpTool[] = [\n {\n name: 'account-me',\n config: {\n description: `Show current ${service} user identity. Returns email, alias (if set), and session expiry information.`,\n inputSchema: {} as const,\n outputSchema: {\n result: z.discriminatedUnion('type', [\n z.object({\n type: z.literal('success'),\n service: z.string(),\n email: z.string(),\n alias: z.string().optional(),\n sessionExpiresIn: z.string().nullable().optional(),\n message: z.string(),\n }),\n ]),\n } as const,\n },\n handler: async (_args: unknown, extra?: unknown): Promise<CallToolResult> => {\n try {\n // Mode-specific implementation\n if (mode === 'stateless') {\n // DCR/Stateless: Extract email from auth context\n const authContext = (extra as { authContext?: { accountId?: string } })?.authContext;\n\n if (!authContext?.accountId) {\n throw new Error('No authentication context available. DCR mode requires bearer token.');\n }\n\n const result = {\n type: 'success' as const,\n service,\n email: authContext.accountId,\n sessionExpiresIn: null, // Client-managed\n message: `Authenticated as ${authContext.accountId}. Session managed by MCP client.`,\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],\n structuredContent: { result },\n };\n }\n\n // Loopback/Device Code/Service Account: Use store\n if (!store) {\n throw new Error('Store is required for non-stateless mode');\n }\n\n // Get active account\n const activeAccountId = await getActiveAccount(store, { service });\n if (!activeAccountId) {\n throw new Error(`No active ${service} account found. Use account-switch to add an account.`);\n }\n\n // Get account info (email, alias)\n const accountInfo = await getAccountInfo(store, { accountId: activeAccountId, service });\n const email = accountInfo?.email ?? activeAccountId;\n const alias = accountInfo?.alias;\n\n // Calculate session expiry\n let sessionExpiresIn: string | null = null;\n try {\n const token = await getToken<CachedToken>(store, { accountId: activeAccountId, service });\n if (token?.expiresAt) {\n const now = Date.now();\n if (token.expiresAt > now) {\n sessionExpiresIn = formatDuration(token.expiresAt - now);\n } else {\n sessionExpiresIn = 'expired';\n }\n } else {\n // No expiry = JWT-based service account or no token info\n sessionExpiresIn = 'never';\n }\n } catch {\n // Token not found or error reading - treat as \"never\" (service account pattern)\n sessionExpiresIn = 'never';\n }\n\n const result = {\n type: 'success' as const,\n service,\n email,\n ...(alias && { alias }),\n ...(sessionExpiresIn && { sessionExpiresIn }),\n message: `Authenticated as ${email}${alias ? ` (${alias})` : ''}${sessionExpiresIn ? `. Session expires in ${sessionExpiresIn}` : ''}.`,\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],\n structuredContent: { result },\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger?.error?.('account-me.error', { service, error: message });\n\n throw new McpError(ErrorCode.InternalError, `Error getting ${service} account info: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n },\n },\n ];\n\n const prompts: McpPrompt[] = [];\n\n return { tools, prompts };\n}\n"],"names":["createAccountMe","formatDuration","ms","totalSeconds","Math","floor","minutes","hours","remainingMinutes","config","service","store","logger","mode","tools","name","description","inputSchema","outputSchema","result","z","discriminatedUnion","object","type","literal","string","email","alias","optional","sessionExpiresIn","nullable","message","handler","_args","extra","authContext","activeAccountId","accountInfo","token","now","error","accountId","Error","content","text","JSON","stringify","structuredContent","getActiveAccount","getAccountInfo","getToken","expiresAt","Date","String","McpError","ErrorCode","InternalError","stack","undefined","prompts"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { Keyv } from 'keyv';
2
+ /**
3
+ * Find account ID by email or alias lookup.
4
+ * Returns accountId if found, otherwise null.
5
+ */
6
+ export declare function findAccountByEmailOrAlias(store: Keyv, service: string, emailOrAlias: string): Promise<string | null>;
@@ -0,0 +1,6 @@
1
+ import type { Keyv } from 'keyv';
2
+ /**
3
+ * Find account ID by email or alias lookup.
4
+ * Returns accountId if found, otherwise null.
5
+ */
6
+ export declare function findAccountByEmailOrAlias(store: Keyv, service: string, emailOrAlias: string): Promise<string | null>;