@graphorin/mcp 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE +21 -0
  3. package/README.md +296 -0
  4. package/dist/client/adapt-result.d.ts +25 -0
  5. package/dist/client/adapt-result.d.ts.map +1 -0
  6. package/dist/client/adapt-result.js +174 -0
  7. package/dist/client/adapt-result.js.map +1 -0
  8. package/dist/client/client-handlers.js +134 -0
  9. package/dist/client/client-handlers.js.map +1 -0
  10. package/dist/client/client.d.ts +21 -0
  11. package/dist/client/client.d.ts.map +1 -0
  12. package/dist/client/client.js +358 -0
  13. package/dist/client/client.js.map +1 -0
  14. package/dist/client/defer-loading.d.ts +7 -0
  15. package/dist/client/defer-loading.d.ts.map +1 -0
  16. package/dist/client/defer-loading.js +81 -0
  17. package/dist/client/defer-loading.js.map +1 -0
  18. package/dist/client/inbound-filters.js +65 -0
  19. package/dist/client/inbound-filters.js.map +1 -0
  20. package/dist/client/index.d.ts +7 -0
  21. package/dist/client/index.js +7 -0
  22. package/dist/client/mcp-resource-reader.d.ts +22 -0
  23. package/dist/client/mcp-resource-reader.d.ts.map +1 -0
  24. package/dist/client/mcp-resource-reader.js +113 -0
  25. package/dist/client/mcp-resource-reader.js.map +1 -0
  26. package/dist/client/pinning.js +41 -0
  27. package/dist/client/pinning.js.map +1 -0
  28. package/dist/client/to-tools.d.ts +41 -0
  29. package/dist/client/to-tools.d.ts.map +1 -0
  30. package/dist/client/to-tools.js +125 -0
  31. package/dist/client/to-tools.js.map +1 -0
  32. package/dist/client/transport-factory.js +86 -0
  33. package/dist/client/transport-factory.js.map +1 -0
  34. package/dist/client/types.d.ts +353 -0
  35. package/dist/client/types.d.ts.map +1 -0
  36. package/dist/errors/index.d.ts +120 -0
  37. package/dist/errors/index.d.ts.map +1 -0
  38. package/dist/errors/index.js +88 -0
  39. package/dist/errors/index.js.map +1 -0
  40. package/dist/helpers/identity.d.ts +22 -0
  41. package/dist/helpers/identity.d.ts.map +1 -0
  42. package/dist/helpers/identity.js +85 -0
  43. package/dist/helpers/identity.js.map +1 -0
  44. package/dist/helpers/index.d.ts +3 -0
  45. package/dist/helpers/index.js +4 -0
  46. package/dist/helpers/validate-config.d.ts +16 -0
  47. package/dist/helpers/validate-config.d.ts.map +1 -0
  48. package/dist/helpers/validate-config.js +61 -0
  49. package/dist/helpers/validate-config.js.map +1 -0
  50. package/dist/index.d.ts +60 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +58 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/oauth/bridge.d.ts +59 -0
  55. package/dist/oauth/bridge.d.ts.map +1 -0
  56. package/dist/oauth/bridge.js +75 -0
  57. package/dist/oauth/bridge.js.map +1 -0
  58. package/dist/oauth/index.d.ts +3 -0
  59. package/dist/oauth/index.js +4 -0
  60. package/dist/oauth/library.d.ts +23 -0
  61. package/dist/oauth/library.d.ts.map +1 -0
  62. package/dist/oauth/library.js +27 -0
  63. package/dist/oauth/library.js.map +1 -0
  64. package/dist/registry/json-schema.js +215 -0
  65. package/dist/registry/json-schema.js.map +1 -0
  66. package/dist/transport/index.d.ts +4 -0
  67. package/dist/transport/index.js +4 -0
  68. package/dist/transport/types.d.ts +93 -0
  69. package/dist/transport/types.d.ts.map +1 -0
  70. package/package.json +105 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/errors/index.ts"],"sourcesContent":["/**\n * Typed error union for the `@graphorin/mcp` package.\n *\n * Every error carries a stable lowercase {@link MCPErrorKind}\n * discriminator, an actionable {@link MCPError.hint} field where\n * applicable, and an optional structured `metadata` bag the audit\n * emitter persists alongside the standard `runId` / `sessionId`\n * context.\n *\n * @packageDocumentation\n */\n\n/**\n * Discriminator union for every error class produced by\n * `@graphorin/mcp`. New kinds extend this union; never throw plain\n * `Error` from framework code.\n *\n * @stable\n */\nexport type MCPErrorKind =\n | 'connection-failed'\n | 'protocol-error'\n | 'auth-error'\n | 'tool-not-found'\n | 'tool-execution'\n | 'pin-mismatch'\n | 'call-timeout'\n | 'cancelled'\n | 'invalid-config'\n | 'session-lost'\n | 'transport-not-supported'\n | 'transport-resumable-not-supported';\n\n/** Common metadata bag attached to every {@link MCPError}. */\nexport interface MCPErrorMetadata {\n readonly server?: string;\n readonly tool?: string;\n readonly transport?: 'stdio' | 'streamable-http' | 'sse';\n readonly cause?: unknown;\n readonly httpStatus?: number;\n readonly sessionId?: string;\n readonly lastEventId?: string;\n}\n\n/**\n * Base class for every typed error produced by `@graphorin/mcp`.\n *\n * @stable\n */\nexport abstract class GraphorinMCPError extends Error {\n /** Lowercase discriminator. */\n public abstract readonly kind: MCPErrorKind;\n /** Optional remediation hint surfaced in CLI output. */\n public readonly hint?: string;\n /** Sanitized metadata; never carries secret material. */\n public readonly metadata: Readonly<MCPErrorMetadata>;\n /** Underlying cause (chained errors). */\n public override readonly cause?: unknown;\n\n public constructor(\n message: string,\n opts: {\n readonly hint?: string;\n readonly metadata?: MCPErrorMetadata;\n readonly cause?: unknown;\n } = {},\n ) {\n super(message);\n this.name = new.target.name;\n if (opts.hint !== undefined) this.hint = opts.hint;\n this.metadata = Object.freeze({ ...(opts.metadata ?? {}) });\n if (opts.cause !== undefined) this.cause = opts.cause;\n }\n}\n\n/** Raised when a transport fails to connect or is dropped unexpectedly. */\nexport class MCPConnectionError extends GraphorinMCPError {\n public readonly kind = 'connection-failed' as const;\n}\n\n/** Raised on JSON-RPC / MCP protocol-level errors. */\nexport class MCPProtocolError extends GraphorinMCPError {\n public readonly kind = 'protocol-error' as const;\n}\n\n/** Raised when an authentication / authorization step fails. */\nexport class MCPAuthError extends GraphorinMCPError {\n public readonly kind = 'auth-error' as const;\n}\n\n/** Raised when {@link MCPClient.callTool} is invoked for an unknown tool. */\nexport class MCPToolNotFoundError extends GraphorinMCPError {\n public readonly kind = 'tool-not-found' as const;\n}\n\n/**\n * Raised when a pinned tool-definition fingerprint does not match the\n * server's current definition and `onPinMismatch: 'reject'` is set\n * (MC-6) — the approve-then-swap rug-pull posture.\n */\nexport class MCPToolPinningError extends GraphorinMCPError {\n public readonly kind = 'pin-mismatch' as const;\n}\n\n/**\n * Raised when the MCP server reports a tool-level failure\n * (`CallToolResult.isError === true`, MC-4). The server's content text\n * rides in the message so the model keeps its self-correction signal —\n * while the executor records a real tool FAILURE (audit, retry and\n * error policies all engage) instead of a fake success.\n */\nexport class MCPToolExecutionError extends GraphorinMCPError {\n public readonly kind = 'tool-execution' as const;\n}\n\n/** Raised when a tool call exceeds its configured timeout / aborts. */\nexport class MCPCallTimeoutError extends GraphorinMCPError {\n public readonly kind: 'call-timeout' | 'session-lost' = 'call-timeout';\n\n public constructor(\n message: string,\n opts: {\n readonly hint?: string;\n readonly metadata?: MCPErrorMetadata;\n readonly cause?: unknown;\n readonly variant?: 'call-timeout' | 'session-lost';\n },\n ) {\n super(message, opts);\n if (opts.variant !== undefined) {\n this.kind = opts.variant;\n }\n }\n}\n\n/** Raised when an in-flight call is cancelled by an `AbortSignal`. */\nexport class MCPCancelledError extends GraphorinMCPError {\n public readonly kind = 'cancelled' as const;\n}\n\n/** Raised on invalid `createMCPClient(...)` configuration. */\nexport class MCPInvalidConfigError extends GraphorinMCPError {\n public readonly kind = 'invalid-config' as const;\n}\n\n/**\n * Raised when an operator requests a transport / capability that the\n * runtime does not support (e.g. `resumable: true` on `stdio`).\n *\n * @stable\n */\nexport class MCPTransportNotSupportedError extends GraphorinMCPError {\n public readonly kind: 'transport-not-supported' | 'transport-resumable-not-supported' =\n 'transport-not-supported';\n\n public constructor(\n message: string,\n opts: {\n readonly hint?: string;\n readonly metadata?: MCPErrorMetadata;\n readonly cause?: unknown;\n readonly variant?: 'transport-not-supported' | 'transport-resumable-not-supported';\n },\n ) {\n super(message, opts);\n if (opts.variant !== undefined) {\n this.kind = opts.variant;\n }\n }\n}\n"],"mappings":";;;;;;AAiDA,IAAsB,oBAAtB,cAAgD,MAAM;;CAIpD,AAAgB;;CAEhB,AAAgB;;CAEhB,AAAyB;CAEzB,AAAO,YACL,SACA,OAII,EAAE,EACN;AACA,QAAM,QAAQ;AACd,OAAK,OAAO,IAAI,OAAO;AACvB,MAAI,KAAK,SAAS,OAAW,MAAK,OAAO,KAAK;AAC9C,OAAK,WAAW,OAAO,OAAO,EAAE,GAAI,KAAK,YAAY,EAAE,EAAG,CAAC;AAC3D,MAAI,KAAK,UAAU,OAAW,MAAK,QAAQ,KAAK;;;;AAKpD,IAAa,qBAAb,cAAwC,kBAAkB;CACxD,AAAgB,OAAO;;;AAIzB,IAAa,mBAAb,cAAsC,kBAAkB;CACtD,AAAgB,OAAO;;;AAIzB,IAAa,eAAb,cAAkC,kBAAkB;CAClD,AAAgB,OAAO;;;AAIzB,IAAa,uBAAb,cAA0C,kBAAkB;CAC1D,AAAgB,OAAO;;;;;;;AAQzB,IAAa,sBAAb,cAAyC,kBAAkB;CACzD,AAAgB,OAAO;;;;;;;;;AAUzB,IAAa,wBAAb,cAA2C,kBAAkB;CAC3D,AAAgB,OAAO;;;AAIzB,IAAa,sBAAb,cAAyC,kBAAkB;CACzD,AAAgB,OAAwC;CAExD,AAAO,YACL,SACA,MAMA;AACA,QAAM,SAAS,KAAK;AACpB,MAAI,KAAK,YAAY,OACnB,MAAK,OAAO,KAAK;;;;AAMvB,IAAa,oBAAb,cAAuC,kBAAkB;CACvD,AAAgB,OAAO;;;AAIzB,IAAa,wBAAb,cAA2C,kBAAkB;CAC3D,AAAgB,OAAO;;;;;;;;AASzB,IAAa,gCAAb,cAAmD,kBAAkB;CACnE,AAAgB,OACd;CAEF,AAAO,YACL,SACA,MAMA;AACA,QAAM,SAAS,KAAK;AACpB,MAAI,KAAK,YAAY,OACnB,MAAK,OAAO,KAAK"}
@@ -0,0 +1,22 @@
1
+ import { MCPTransportConfig, ServerIdentity } from "../transport/types.js";
2
+
3
+ //#region src/helpers/identity.d.ts
4
+
5
+ /**
6
+ * Compute the canonical {@link ServerIdentity} for the supplied
7
+ * transport. The id is suitable for use as a registry key and as the
8
+ * operator-facing label in audit rows + trace attributes.
9
+ *
10
+ * @stable
11
+ */
12
+ declare function deriveServerIdentity(transport: MCPTransportConfig, serverInfoName?: string): ServerIdentity;
13
+ /**
14
+ * Operator-facing single-line label for a {@link MCPTransportConfig}.
15
+ * Suitable for trace attributes, audit rows, and CLI output.
16
+ *
17
+ * @stable
18
+ */
19
+ declare function formatMCPServerName(transport: MCPTransportConfig): string;
20
+ //#endregion
21
+ export { deriveServerIdentity, formatMCPServerName };
22
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","names":[],"sources":["../../src/helpers/identity.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;iBAyBgB,oBAAA,YACH,8CAEV;;;;;;;iBA0Ea,mBAAA,YAA+B"}
@@ -0,0 +1,85 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ //#region src/helpers/identity.ts
4
+ /**
5
+ * Helpers for deriving stable {@link ServerIdentity} records from the
6
+ * supplied {@link MCPTransportConfig}, plus the operator-facing
7
+ * formatter the audit emitter and the trace span attributes use.
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ /**
12
+ * Compute the canonical {@link ServerIdentity} for the supplied
13
+ * transport. The id is suitable for use as a registry key and as the
14
+ * operator-facing label in audit rows + trace attributes.
15
+ *
16
+ * @stable
17
+ */
18
+ function deriveServerIdentity(transport, serverInfoName) {
19
+ switch (transport.kind) {
20
+ case "stdio": return deriveStdioIdentity(transport, serverInfoName);
21
+ case "streamable-http": return deriveStreamableHttpIdentity(transport, serverInfoName);
22
+ case "sse": return deriveSseIdentity(transport, serverInfoName);
23
+ }
24
+ }
25
+ function deriveStdioIdentity(transport, serverInfoName) {
26
+ const argsHash = createHash("sha256").update((transport.args ?? []).join("\0")).digest("hex").slice(0, 16);
27
+ const command = basenameWithoutExt(transport.command);
28
+ const id = serverInfoName ?? `${command}-${argsHash}`;
29
+ return Object.freeze({
30
+ kind: "mcp-stdio",
31
+ id,
32
+ command,
33
+ argsHash,
34
+ ...serverInfoName === void 0 ? {} : { serverInfoName }
35
+ });
36
+ }
37
+ function deriveStreamableHttpIdentity(transport, serverInfoName) {
38
+ const url = new URL(typeof transport.url === "string" ? transport.url : transport.url.toString());
39
+ const urlHostname = url.hostname;
40
+ const urlPath = url.pathname.length === 0 ? "/" : url.pathname;
41
+ const id = serverInfoName ?? `${urlHostname}${urlPath}`;
42
+ return Object.freeze({
43
+ kind: "mcp-streamable-http",
44
+ id,
45
+ urlHostname,
46
+ urlPath,
47
+ ...serverInfoName === void 0 ? {} : { serverInfoName }
48
+ });
49
+ }
50
+ function deriveSseIdentity(transport, serverInfoName) {
51
+ const url = new URL(typeof transport.url === "string" ? transport.url : transport.url.toString());
52
+ const urlHostname = url.hostname;
53
+ const urlPath = url.pathname.length === 0 ? "/" : url.pathname;
54
+ const id = serverInfoName ?? `${urlHostname}${urlPath}`;
55
+ return Object.freeze({
56
+ kind: "mcp-sse",
57
+ id,
58
+ urlHostname,
59
+ urlPath,
60
+ ...serverInfoName === void 0 ? {} : { serverInfoName }
61
+ });
62
+ }
63
+ function basenameWithoutExt(command) {
64
+ const slashIdx = Math.max(command.lastIndexOf("/"), command.lastIndexOf("\\"));
65
+ const base = slashIdx === -1 ? command : command.slice(slashIdx + 1);
66
+ const dotIdx = base.lastIndexOf(".");
67
+ return dotIdx <= 0 ? base : base.slice(0, dotIdx);
68
+ }
69
+ /**
70
+ * Operator-facing single-line label for a {@link MCPTransportConfig}.
71
+ * Suitable for trace attributes, audit rows, and CLI output.
72
+ *
73
+ * @stable
74
+ */
75
+ function formatMCPServerName(transport) {
76
+ switch (transport.kind) {
77
+ case "stdio": return `stdio:${basenameWithoutExt(transport.command)}${(transport.args ?? []).length === 0 ? "" : ` ${(transport.args ?? []).join(" ")}`}`;
78
+ case "streamable-http": return `streamable-http:${typeof transport.url === "string" ? transport.url : transport.url.toString()}`;
79
+ case "sse": return `sse:${typeof transport.url === "string" ? transport.url : transport.url.toString()}`;
80
+ }
81
+ }
82
+
83
+ //#endregion
84
+ export { deriveServerIdentity, formatMCPServerName };
85
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","names":[],"sources":["../../src/helpers/identity.ts"],"sourcesContent":["/**\n * Helpers for deriving stable {@link ServerIdentity} records from the\n * supplied {@link MCPTransportConfig}, plus the operator-facing\n * formatter the audit emitter and the trace span attributes use.\n *\n * @packageDocumentation\n */\n\nimport { createHash } from 'node:crypto';\n\nimport type {\n MCPTransportConfig,\n ServerIdentity,\n SseTransportConfig,\n StdioTransportConfig,\n StreamableHttpTransportConfig,\n} from '../transport/types.js';\n\n/**\n * Compute the canonical {@link ServerIdentity} for the supplied\n * transport. The id is suitable for use as a registry key and as the\n * operator-facing label in audit rows + trace attributes.\n *\n * @stable\n */\nexport function deriveServerIdentity(\n transport: MCPTransportConfig,\n serverInfoName?: string,\n): ServerIdentity {\n switch (transport.kind) {\n case 'stdio':\n return deriveStdioIdentity(transport, serverInfoName);\n case 'streamable-http':\n return deriveStreamableHttpIdentity(transport, serverInfoName);\n case 'sse':\n return deriveSseIdentity(transport, serverInfoName);\n }\n}\n\nfunction deriveStdioIdentity(\n transport: StdioTransportConfig,\n serverInfoName?: string,\n): ServerIdentity {\n const argsHash = createHash('sha256')\n .update((transport.args ?? []).join('\\u0000'))\n .digest('hex')\n .slice(0, 16);\n const command = basenameWithoutExt(transport.command);\n const id = serverInfoName ?? `${command}-${argsHash}`;\n return Object.freeze({\n kind: 'mcp-stdio',\n id,\n command,\n argsHash,\n ...(serverInfoName === undefined ? {} : { serverInfoName }),\n });\n}\n\nfunction deriveStreamableHttpIdentity(\n transport: StreamableHttpTransportConfig,\n serverInfoName?: string,\n): ServerIdentity {\n const url = new URL(typeof transport.url === 'string' ? transport.url : transport.url.toString());\n const urlHostname = url.hostname;\n const urlPath = url.pathname.length === 0 ? '/' : url.pathname;\n const id = serverInfoName ?? `${urlHostname}${urlPath}`;\n return Object.freeze({\n kind: 'mcp-streamable-http',\n id,\n urlHostname,\n urlPath,\n ...(serverInfoName === undefined ? {} : { serverInfoName }),\n });\n}\n\nfunction deriveSseIdentity(transport: SseTransportConfig, serverInfoName?: string): ServerIdentity {\n const url = new URL(typeof transport.url === 'string' ? transport.url : transport.url.toString());\n const urlHostname = url.hostname;\n const urlPath = url.pathname.length === 0 ? '/' : url.pathname;\n const id = serverInfoName ?? `${urlHostname}${urlPath}`;\n return Object.freeze({\n kind: 'mcp-sse',\n id,\n urlHostname,\n urlPath,\n ...(serverInfoName === undefined ? {} : { serverInfoName }),\n });\n}\n\nfunction basenameWithoutExt(command: string): string {\n const slashIdx = Math.max(command.lastIndexOf('/'), command.lastIndexOf('\\\\'));\n const base = slashIdx === -1 ? command : command.slice(slashIdx + 1);\n const dotIdx = base.lastIndexOf('.');\n return dotIdx <= 0 ? base : base.slice(0, dotIdx);\n}\n\n/**\n * Operator-facing single-line label for a {@link MCPTransportConfig}.\n * Suitable for trace attributes, audit rows, and CLI output.\n *\n * @stable\n */\nexport function formatMCPServerName(transport: MCPTransportConfig): string {\n switch (transport.kind) {\n case 'stdio':\n return `stdio:${basenameWithoutExt(transport.command)}${\n (transport.args ?? []).length === 0 ? '' : ` ${(transport.args ?? []).join(' ')}`\n }`;\n case 'streamable-http':\n return `streamable-http:${typeof transport.url === 'string' ? transport.url : transport.url.toString()}`;\n case 'sse':\n return `sse:${typeof transport.url === 'string' ? transport.url : transport.url.toString()}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAyBA,SAAgB,qBACd,WACA,gBACgB;AAChB,SAAQ,UAAU,MAAlB;EACE,KAAK,QACH,QAAO,oBAAoB,WAAW,eAAe;EACvD,KAAK,kBACH,QAAO,6BAA6B,WAAW,eAAe;EAChE,KAAK,MACH,QAAO,kBAAkB,WAAW,eAAe;;;AAIzD,SAAS,oBACP,WACA,gBACgB;CAChB,MAAM,WAAW,WAAW,SAAS,CAClC,QAAQ,UAAU,QAAQ,EAAE,EAAE,KAAK,KAAS,CAAC,CAC7C,OAAO,MAAM,CACb,MAAM,GAAG,GAAG;CACf,MAAM,UAAU,mBAAmB,UAAU,QAAQ;CACrD,MAAM,KAAK,kBAAkB,GAAG,QAAQ,GAAG;AAC3C,QAAO,OAAO,OAAO;EACnB,MAAM;EACN;EACA;EACA;EACA,GAAI,mBAAmB,SAAY,EAAE,GAAG,EAAE,gBAAgB;EAC3D,CAAC;;AAGJ,SAAS,6BACP,WACA,gBACgB;CAChB,MAAM,MAAM,IAAI,IAAI,OAAO,UAAU,QAAQ,WAAW,UAAU,MAAM,UAAU,IAAI,UAAU,CAAC;CACjG,MAAM,cAAc,IAAI;CACxB,MAAM,UAAU,IAAI,SAAS,WAAW,IAAI,MAAM,IAAI;CACtD,MAAM,KAAK,kBAAkB,GAAG,cAAc;AAC9C,QAAO,OAAO,OAAO;EACnB,MAAM;EACN;EACA;EACA;EACA,GAAI,mBAAmB,SAAY,EAAE,GAAG,EAAE,gBAAgB;EAC3D,CAAC;;AAGJ,SAAS,kBAAkB,WAA+B,gBAAyC;CACjG,MAAM,MAAM,IAAI,IAAI,OAAO,UAAU,QAAQ,WAAW,UAAU,MAAM,UAAU,IAAI,UAAU,CAAC;CACjG,MAAM,cAAc,IAAI;CACxB,MAAM,UAAU,IAAI,SAAS,WAAW,IAAI,MAAM,IAAI;CACtD,MAAM,KAAK,kBAAkB,GAAG,cAAc;AAC9C,QAAO,OAAO,OAAO;EACnB,MAAM;EACN;EACA;EACA;EACA,GAAI,mBAAmB,SAAY,EAAE,GAAG,EAAE,gBAAgB;EAC3D,CAAC;;AAGJ,SAAS,mBAAmB,SAAyB;CACnD,MAAM,WAAW,KAAK,IAAI,QAAQ,YAAY,IAAI,EAAE,QAAQ,YAAY,KAAK,CAAC;CAC9E,MAAM,OAAO,aAAa,KAAK,UAAU,QAAQ,MAAM,WAAW,EAAE;CACpE,MAAM,SAAS,KAAK,YAAY,IAAI;AACpC,QAAO,UAAU,IAAI,OAAO,KAAK,MAAM,GAAG,OAAO;;;;;;;;AASnD,SAAgB,oBAAoB,WAAuC;AACzE,SAAQ,UAAU,MAAlB;EACE,KAAK,QACH,QAAO,SAAS,mBAAmB,UAAU,QAAQ,IAClD,UAAU,QAAQ,EAAE,EAAE,WAAW,IAAI,KAAK,KAAK,UAAU,QAAQ,EAAE,EAAE,KAAK,IAAI;EAEnF,KAAK,kBACH,QAAO,mBAAmB,OAAO,UAAU,QAAQ,WAAW,UAAU,MAAM,UAAU,IAAI,UAAU;EACxG,KAAK,MACH,QAAO,OAAO,OAAO,UAAU,QAAQ,WAAW,UAAU,MAAM,UAAU,IAAI,UAAU"}
@@ -0,0 +1,3 @@
1
+ import { deriveServerIdentity, formatMCPServerName } from "./identity.js";
2
+ import { validateMCPServerConfig } from "./validate-config.js";
3
+ export { deriveServerIdentity, formatMCPServerName, validateMCPServerConfig };
@@ -0,0 +1,4 @@
1
+ import { deriveServerIdentity, formatMCPServerName } from "./identity.js";
2
+ import { validateMCPServerConfig } from "./validate-config.js";
3
+
4
+ export { deriveServerIdentity, formatMCPServerName, validateMCPServerConfig };
@@ -0,0 +1,16 @@
1
+ import { MCPTransportConfig } from "../transport/types.js";
2
+
3
+ //#region src/helpers/validate-config.d.ts
4
+
5
+ /**
6
+ * Throws {@link MCPInvalidConfigError} on invalid configuration.
7
+ *
8
+ * @stable
9
+ */
10
+ declare function validateMCPServerConfig(opts: {
11
+ readonly transport: MCPTransportConfig;
12
+ readonly resumable?: boolean;
13
+ }): void;
14
+ //#endregion
15
+ export { validateMCPServerConfig };
16
+ //# sourceMappingURL=validate-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-config.d.ts","names":[],"sources":["../../src/helpers/validate-config.ts"],"sourcesContent":[],"mappings":";;;;;;;;;iBAqBgB,uBAAA;sBACM"}
@@ -0,0 +1,61 @@
1
+ import { MCPInvalidConfigError, MCPTransportNotSupportedError } from "../errors/index.js";
2
+
3
+ //#region src/helpers/validate-config.ts
4
+ /**
5
+ * `validateMCPServerConfig(...)` — sanity-check a transport configuration
6
+ * before {@link createMCPClient} runs the network-level handshake.
7
+ *
8
+ * The validator catches the most common configuration mistakes
9
+ * (missing url for HTTP transports, empty command for stdio,
10
+ * unsupported `resumable: true` for stdio / sse, …) and surfaces them
11
+ * as {@link MCPInvalidConfigError} so the operator does not have to
12
+ * read a transport-specific stack trace.
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+ /**
17
+ * Throws {@link MCPInvalidConfigError} on invalid configuration.
18
+ *
19
+ * @stable
20
+ */
21
+ function validateMCPServerConfig(opts) {
22
+ validateTransport(opts.transport);
23
+ if (opts.resumable === true) {
24
+ if (opts.transport.kind === "stdio") throw new MCPTransportNotSupportedError("Resumable streaming sessions are not supported on the stdio transport.", {
25
+ variant: "transport-resumable-not-supported",
26
+ metadata: { transport: "stdio" },
27
+ hint: "Use the streamable-http transport when you need Mcp-Session-Id + Last-Event-ID resume semantics."
28
+ });
29
+ if (opts.transport.kind === "sse") throw new MCPTransportNotSupportedError("Resumable streaming sessions are not supported on the deprecated sse transport.", {
30
+ variant: "transport-resumable-not-supported",
31
+ metadata: { transport: "sse" },
32
+ hint: "Migrate to the streamable-http transport for resumable session support."
33
+ });
34
+ }
35
+ }
36
+ function validateTransport(transport) {
37
+ switch (transport.kind) {
38
+ case "stdio":
39
+ if (typeof transport.command !== "string" || transport.command.length === 0) throw new MCPInvalidConfigError("stdio transport requires a non-empty `command`.", { metadata: { transport: "stdio" } });
40
+ if (transport.args !== void 0 && !Array.isArray(transport.args)) throw new MCPInvalidConfigError("stdio transport `args` must be an array of strings.", { metadata: { transport: "stdio" } });
41
+ return;
42
+ case "streamable-http":
43
+ case "sse":
44
+ if (transport.url === void 0 || transport.url === null || transport.url === "") throw new MCPInvalidConfigError(`${transport.kind} transport requires a non-empty \`url\`.`, { metadata: { transport: transport.kind } });
45
+ try {
46
+ const candidate = typeof transport.url === "string" ? new URL(transport.url) : transport.url;
47
+ if (candidate.protocol !== "http:" && candidate.protocol !== "https:") throw new MCPInvalidConfigError(`${transport.kind} transport \`url\` must use http: or https: (got ${candidate.protocol}).`, { metadata: { transport: transport.kind } });
48
+ } catch (cause) {
49
+ if (cause instanceof MCPInvalidConfigError) throw cause;
50
+ throw new MCPInvalidConfigError(`${transport.kind} transport \`url\` is not a valid URL.`, {
51
+ metadata: { transport: transport.kind },
52
+ cause
53
+ });
54
+ }
55
+ return;
56
+ }
57
+ }
58
+
59
+ //#endregion
60
+ export { validateMCPServerConfig };
61
+ //# sourceMappingURL=validate-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-config.js","names":[],"sources":["../../src/helpers/validate-config.ts"],"sourcesContent":["/**\n * `validateMCPServerConfig(...)` — sanity-check a transport configuration\n * before {@link createMCPClient} runs the network-level handshake.\n *\n * The validator catches the most common configuration mistakes\n * (missing url for HTTP transports, empty command for stdio,\n * unsupported `resumable: true` for stdio / sse, …) and surfaces them\n * as {@link MCPInvalidConfigError} so the operator does not have to\n * read a transport-specific stack trace.\n *\n * @packageDocumentation\n */\n\nimport { MCPInvalidConfigError, MCPTransportNotSupportedError } from '../errors/index.js';\nimport type { MCPTransportConfig } from '../transport/types.js';\n\n/**\n * Throws {@link MCPInvalidConfigError} on invalid configuration.\n *\n * @stable\n */\nexport function validateMCPServerConfig(opts: {\n readonly transport: MCPTransportConfig;\n readonly resumable?: boolean;\n}): void {\n validateTransport(opts.transport);\n if (opts.resumable === true) {\n if (opts.transport.kind === 'stdio') {\n throw new MCPTransportNotSupportedError(\n 'Resumable streaming sessions are not supported on the stdio transport.',\n {\n variant: 'transport-resumable-not-supported',\n metadata: { transport: 'stdio' },\n hint: 'Use the streamable-http transport when you need Mcp-Session-Id + Last-Event-ID resume semantics.',\n },\n );\n }\n if (opts.transport.kind === 'sse') {\n throw new MCPTransportNotSupportedError(\n 'Resumable streaming sessions are not supported on the deprecated sse transport.',\n {\n variant: 'transport-resumable-not-supported',\n metadata: { transport: 'sse' },\n hint: 'Migrate to the streamable-http transport for resumable session support.',\n },\n );\n }\n }\n}\n\nfunction validateTransport(transport: MCPTransportConfig): void {\n switch (transport.kind) {\n case 'stdio': {\n if (typeof transport.command !== 'string' || transport.command.length === 0) {\n throw new MCPInvalidConfigError('stdio transport requires a non-empty `command`.', {\n metadata: { transport: 'stdio' },\n });\n }\n if (transport.args !== undefined && !Array.isArray(transport.args)) {\n throw new MCPInvalidConfigError('stdio transport `args` must be an array of strings.', {\n metadata: { transport: 'stdio' },\n });\n }\n return;\n }\n case 'streamable-http':\n case 'sse': {\n if (transport.url === undefined || transport.url === null || transport.url === '') {\n throw new MCPInvalidConfigError(\n `${transport.kind} transport requires a non-empty \\`url\\`.`,\n {\n metadata: { transport: transport.kind },\n },\n );\n }\n try {\n const candidate =\n typeof transport.url === 'string' ? new URL(transport.url) : transport.url;\n if (candidate.protocol !== 'http:' && candidate.protocol !== 'https:') {\n throw new MCPInvalidConfigError(\n `${transport.kind} transport \\`url\\` must use http: or https: (got ${candidate.protocol}).`,\n { metadata: { transport: transport.kind } },\n );\n }\n } catch (cause) {\n if (cause instanceof MCPInvalidConfigError) throw cause;\n throw new MCPInvalidConfigError(`${transport.kind} transport \\`url\\` is not a valid URL.`, {\n metadata: { transport: transport.kind },\n cause,\n });\n }\n return;\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,wBAAwB,MAG/B;AACP,mBAAkB,KAAK,UAAU;AACjC,KAAI,KAAK,cAAc,MAAM;AAC3B,MAAI,KAAK,UAAU,SAAS,QAC1B,OAAM,IAAI,8BACR,0EACA;GACE,SAAS;GACT,UAAU,EAAE,WAAW,SAAS;GAChC,MAAM;GACP,CACF;AAEH,MAAI,KAAK,UAAU,SAAS,MAC1B,OAAM,IAAI,8BACR,mFACA;GACE,SAAS;GACT,UAAU,EAAE,WAAW,OAAO;GAC9B,MAAM;GACP,CACF;;;AAKP,SAAS,kBAAkB,WAAqC;AAC9D,SAAQ,UAAU,MAAlB;EACE,KAAK;AACH,OAAI,OAAO,UAAU,YAAY,YAAY,UAAU,QAAQ,WAAW,EACxE,OAAM,IAAI,sBAAsB,mDAAmD,EACjF,UAAU,EAAE,WAAW,SAAS,EACjC,CAAC;AAEJ,OAAI,UAAU,SAAS,UAAa,CAAC,MAAM,QAAQ,UAAU,KAAK,CAChE,OAAM,IAAI,sBAAsB,uDAAuD,EACrF,UAAU,EAAE,WAAW,SAAS,EACjC,CAAC;AAEJ;EAEF,KAAK;EACL,KAAK;AACH,OAAI,UAAU,QAAQ,UAAa,UAAU,QAAQ,QAAQ,UAAU,QAAQ,GAC7E,OAAM,IAAI,sBACR,GAAG,UAAU,KAAK,2CAClB,EACE,UAAU,EAAE,WAAW,UAAU,MAAM,EACxC,CACF;AAEH,OAAI;IACF,MAAM,YACJ,OAAO,UAAU,QAAQ,WAAW,IAAI,IAAI,UAAU,IAAI,GAAG,UAAU;AACzE,QAAI,UAAU,aAAa,WAAW,UAAU,aAAa,SAC3D,OAAM,IAAI,sBACR,GAAG,UAAU,KAAK,mDAAmD,UAAU,SAAS,KACxF,EAAE,UAAU,EAAE,WAAW,UAAU,MAAM,EAAE,CAC5C;YAEI,OAAO;AACd,QAAI,iBAAiB,sBAAuB,OAAM;AAClD,UAAM,IAAI,sBAAsB,GAAG,UAAU,KAAK,yCAAyC;KACzF,UAAU,EAAE,WAAW,UAAU,MAAM;KACvC;KACD,CAAC;;AAEJ"}
@@ -0,0 +1,60 @@
1
+ import { MCPTransportConfig, ServerIdentity, SseTransportConfig, StdioTransportConfig, StreamableHttpTransportConfig } from "./transport/types.js";
2
+ import { OAuthAuthorizationProvider, OAuthAuthorizationProviderOptions, createOAuthAuthorizationProvider } from "./oauth/bridge.js";
3
+ import { CreateMCPClientOptions, MCPCallToolResult, MCPClient, MCPContentPart, MCPElicitationHandler, MCPElicitationRequest, MCPElicitationResult, MCPPromptDefinition, MCPPromptMessage, MCPResourceContent, MCPResourceDefinition, MCPSamplingContent, MCPSamplingHandler, MCPSamplingMessage, MCPSamplingRequest, MCPSamplingResult, MCPToToolsOptions, MCPToolDefinition } from "./client/types.js";
4
+ import { _resetSseWarnDedupForTesting, createMCPClient } from "./client/client.js";
5
+ import { McpResourceReaderOptions, createMcpResourceReader } from "./client/mcp-resource-reader.js";
6
+ import { adaptCallResult } from "./client/adapt-result.js";
7
+ import { DEFAULT_DEFER_LOADING_THRESHOLD } from "./client/defer-loading.js";
8
+ import { _resetMcpAdapterDedupForTesting, adaptMCPTools } from "./client/to-tools.js";
9
+ import "./client/index.js";
10
+ import { GraphorinMCPError, MCPAuthError, MCPCallTimeoutError, MCPCancelledError, MCPConnectionError, MCPErrorKind, MCPErrorMetadata, MCPInvalidConfigError, MCPProtocolError, MCPToolExecutionError, MCPToolNotFoundError, MCPToolPinningError, MCPTransportNotSupportedError } from "./errors/index.js";
11
+ import { deriveServerIdentity, formatMCPServerName } from "./helpers/identity.js";
12
+ import { validateMCPServerConfig } from "./helpers/validate-config.js";
13
+ import { mcpAuthListSessions, mcpAuthLogin, mcpAuthRefresh, mcpAuthRevoke, mcpAuthStatus } from "./oauth/library.js";
14
+ import "./oauth/index.js";
15
+
16
+ //#region src/index.d.ts
17
+
18
+ /**
19
+ * `@graphorin/mcp` — Model Context Protocol client for the Graphorin
20
+ * framework.
21
+ *
22
+ * The package owns:
23
+ *
24
+ * - The {@link createMCPClient} factory that opens a typed MCP
25
+ * connection over stdio, Streamable HTTP, or the deprecated SSE
26
+ * transport.
27
+ * - The {@link MCPClient} surface (`listTools` / `listResources` /
28
+ * `listPrompts` / `callTool` / `readResource` / `getPrompt` /
29
+ * `close`) plus the strategy-aware {@link MCPClient.toTools}
30
+ * adapter that bridges MCP tool descriptors into Graphorin
31
+ * {@link Tool} records.
32
+ * - The OAuth bridge that resolves bearer headers from the
33
+ * {@link OAuthAuthorizationProvider} backed by
34
+ * `@graphorin/security/oauth`.
35
+ * - Library helpers (`mcpAuthLogin`, `mcpAuthListSessions`,
36
+ * `mcpAuthRefresh`, `mcpAuthRevoke`, `mcpAuthStatus`) consumed by
37
+ * the upcoming `graphorin auth` CLI surface.
38
+ * - Typed errors ({@link MCPConnectionError},
39
+ * {@link MCPProtocolError}, {@link MCPAuthError},
40
+ * {@link MCPToolNotFoundError}, {@link MCPCallTimeoutError},
41
+ * {@link MCPCancelledError}, {@link MCPInvalidConfigError},
42
+ * {@link MCPTransportNotSupportedError}, {@link GraphorinMCPError}).
43
+ *
44
+ * Stable sub-paths:
45
+ *
46
+ * ```ts
47
+ * import { createMCPClient } from '@graphorin/mcp/client';
48
+ * import { createOAuthAuthorizationProvider } from '@graphorin/mcp/oauth';
49
+ * import { formatMCPServerName, validateMCPServerConfig } from '@graphorin/mcp/helpers';
50
+ * import { MCPConnectionError } from '@graphorin/mcp/errors';
51
+ * import type { MCPTransportConfig, ServerIdentity } from '@graphorin/mcp/transport';
52
+ * ```
53
+ *
54
+ * @packageDocumentation
55
+ */
56
+ /** Canonical version constant. Mirrors the `package.json` version. */
57
+ declare const VERSION = "0.5.0";
58
+ //#endregion
59
+ export { CreateMCPClientOptions, DEFAULT_DEFER_LOADING_THRESHOLD, GraphorinMCPError, MCPAuthError, MCPCallTimeoutError, MCPCallToolResult, MCPCancelledError, MCPClient, MCPConnectionError, MCPContentPart, MCPElicitationHandler, MCPElicitationRequest, MCPElicitationResult, MCPErrorKind, MCPErrorMetadata, MCPInvalidConfigError, MCPPromptDefinition, MCPPromptMessage, MCPProtocolError, MCPResourceContent, MCPResourceDefinition, MCPSamplingContent, MCPSamplingHandler, MCPSamplingMessage, MCPSamplingRequest, MCPSamplingResult, MCPToToolsOptions, MCPToolDefinition, MCPToolExecutionError, MCPToolNotFoundError, MCPToolPinningError, MCPTransportConfig, MCPTransportNotSupportedError, McpResourceReaderOptions, OAuthAuthorizationProvider, OAuthAuthorizationProviderOptions, ServerIdentity, SseTransportConfig, StdioTransportConfig, StreamableHttpTransportConfig, VERSION, _resetMcpAdapterDedupForTesting, _resetSseWarnDedupForTesting, adaptCallResult, adaptMCPTools, createMCPClient, createMcpResourceReader, createOAuthAuthorizationProvider, deriveServerIdentity, formatMCPServerName, mcpAuthListSessions, mcpAuthLogin, mcpAuthRefresh, mcpAuthRevoke, mcpAuthStatus, validateMCPServerConfig };
60
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA;;;;;;;;;;;;;;;;;;;;;;;cAAa,OAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,58 @@
1
+ import { GraphorinMCPError, MCPAuthError, MCPCallTimeoutError, MCPCancelledError, MCPConnectionError, MCPInvalidConfigError, MCPProtocolError, MCPToolExecutionError, MCPToolNotFoundError, MCPToolPinningError, MCPTransportNotSupportedError } from "./errors/index.js";
2
+ import { deriveServerIdentity, formatMCPServerName } from "./helpers/identity.js";
3
+ import { validateMCPServerConfig } from "./helpers/validate-config.js";
4
+ import { adaptCallResult } from "./client/adapt-result.js";
5
+ import { DEFAULT_DEFER_LOADING_THRESHOLD } from "./client/defer-loading.js";
6
+ import { _resetMcpAdapterDedupForTesting, adaptMCPTools } from "./client/to-tools.js";
7
+ import { _resetSseWarnDedupForTesting, createMCPClient } from "./client/client.js";
8
+ import { createMcpResourceReader } from "./client/mcp-resource-reader.js";
9
+ import "./client/index.js";
10
+ import { createOAuthAuthorizationProvider } from "./oauth/bridge.js";
11
+ import { mcpAuthListSessions, mcpAuthLogin, mcpAuthRefresh, mcpAuthRevoke, mcpAuthStatus } from "./oauth/library.js";
12
+ import "./oauth/index.js";
13
+
14
+ //#region src/index.ts
15
+ /**
16
+ * `@graphorin/mcp` — Model Context Protocol client for the Graphorin
17
+ * framework.
18
+ *
19
+ * The package owns:
20
+ *
21
+ * - The {@link createMCPClient} factory that opens a typed MCP
22
+ * connection over stdio, Streamable HTTP, or the deprecated SSE
23
+ * transport.
24
+ * - The {@link MCPClient} surface (`listTools` / `listResources` /
25
+ * `listPrompts` / `callTool` / `readResource` / `getPrompt` /
26
+ * `close`) plus the strategy-aware {@link MCPClient.toTools}
27
+ * adapter that bridges MCP tool descriptors into Graphorin
28
+ * {@link Tool} records.
29
+ * - The OAuth bridge that resolves bearer headers from the
30
+ * {@link OAuthAuthorizationProvider} backed by
31
+ * `@graphorin/security/oauth`.
32
+ * - Library helpers (`mcpAuthLogin`, `mcpAuthListSessions`,
33
+ * `mcpAuthRefresh`, `mcpAuthRevoke`, `mcpAuthStatus`) consumed by
34
+ * the upcoming `graphorin auth` CLI surface.
35
+ * - Typed errors ({@link MCPConnectionError},
36
+ * {@link MCPProtocolError}, {@link MCPAuthError},
37
+ * {@link MCPToolNotFoundError}, {@link MCPCallTimeoutError},
38
+ * {@link MCPCancelledError}, {@link MCPInvalidConfigError},
39
+ * {@link MCPTransportNotSupportedError}, {@link GraphorinMCPError}).
40
+ *
41
+ * Stable sub-paths:
42
+ *
43
+ * ```ts
44
+ * import { createMCPClient } from '@graphorin/mcp/client';
45
+ * import { createOAuthAuthorizationProvider } from '@graphorin/mcp/oauth';
46
+ * import { formatMCPServerName, validateMCPServerConfig } from '@graphorin/mcp/helpers';
47
+ * import { MCPConnectionError } from '@graphorin/mcp/errors';
48
+ * import type { MCPTransportConfig, ServerIdentity } from '@graphorin/mcp/transport';
49
+ * ```
50
+ *
51
+ * @packageDocumentation
52
+ */
53
+ /** Canonical version constant. Mirrors the `package.json` version. */
54
+ const VERSION = "0.5.0";
55
+
56
+ //#endregion
57
+ export { DEFAULT_DEFER_LOADING_THRESHOLD, GraphorinMCPError, MCPAuthError, MCPCallTimeoutError, MCPCancelledError, MCPConnectionError, MCPInvalidConfigError, MCPProtocolError, MCPToolExecutionError, MCPToolNotFoundError, MCPToolPinningError, MCPTransportNotSupportedError, VERSION, _resetMcpAdapterDedupForTesting, _resetSseWarnDedupForTesting, adaptCallResult, adaptMCPTools, createMCPClient, createMcpResourceReader, createOAuthAuthorizationProvider, deriveServerIdentity, formatMCPServerName, mcpAuthListSessions, mcpAuthLogin, mcpAuthRefresh, mcpAuthRevoke, mcpAuthStatus, validateMCPServerConfig };
58
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * `@graphorin/mcp` — Model Context Protocol client for the Graphorin\n * framework.\n *\n * The package owns:\n *\n * - The {@link createMCPClient} factory that opens a typed MCP\n * connection over stdio, Streamable HTTP, or the deprecated SSE\n * transport.\n * - The {@link MCPClient} surface (`listTools` / `listResources` /\n * `listPrompts` / `callTool` / `readResource` / `getPrompt` /\n * `close`) plus the strategy-aware {@link MCPClient.toTools}\n * adapter that bridges MCP tool descriptors into Graphorin\n * {@link Tool} records.\n * - The OAuth bridge that resolves bearer headers from the\n * {@link OAuthAuthorizationProvider} backed by\n * `@graphorin/security/oauth`.\n * - Library helpers (`mcpAuthLogin`, `mcpAuthListSessions`,\n * `mcpAuthRefresh`, `mcpAuthRevoke`, `mcpAuthStatus`) consumed by\n * the upcoming `graphorin auth` CLI surface.\n * - Typed errors ({@link MCPConnectionError},\n * {@link MCPProtocolError}, {@link MCPAuthError},\n * {@link MCPToolNotFoundError}, {@link MCPCallTimeoutError},\n * {@link MCPCancelledError}, {@link MCPInvalidConfigError},\n * {@link MCPTransportNotSupportedError}, {@link GraphorinMCPError}).\n *\n * Stable sub-paths:\n *\n * ```ts\n * import { createMCPClient } from '@graphorin/mcp/client';\n * import { createOAuthAuthorizationProvider } from '@graphorin/mcp/oauth';\n * import { formatMCPServerName, validateMCPServerConfig } from '@graphorin/mcp/helpers';\n * import { MCPConnectionError } from '@graphorin/mcp/errors';\n * import type { MCPTransportConfig, ServerIdentity } from '@graphorin/mcp/transport';\n * ```\n *\n * @packageDocumentation\n */\n\n/** Canonical version constant. Mirrors the `package.json` version. */\nexport const VERSION = '0.5.0';\n\nexport * from './client/index.js';\nexport * from './errors/index.js';\nexport * from './helpers/index.js';\nexport * from './oauth/index.js';\nexport * from './transport/index.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,MAAa,UAAU"}
@@ -0,0 +1,59 @@
1
+ import { OAuthSession } from "@graphorin/security/oauth";
2
+ import * as _graphorin_core_contracts0 from "@graphorin/core/contracts";
3
+ import { OAuthServerStore } from "@graphorin/core/contracts";
4
+
5
+ //#region src/oauth/bridge.d.ts
6
+
7
+ /** Options accepted by {@link createOAuthAuthorizationProvider}. */
8
+ interface OAuthAuthorizationProviderOptions {
9
+ /**
10
+ * Secrets store the persisted tokens resolve from (SPL-1) — with it,
11
+ * the bridge issues Authorization headers across process restarts.
12
+ */
13
+ readonly secretsStore?: _graphorin_core_contracts0.SecretsStore;
14
+ /** Stable identifier of the persisted OAuth server (`serverId`). */
15
+ readonly serverId: string;
16
+ /** Persistent storage. */
17
+ readonly storage: OAuthServerStore;
18
+ /**
19
+ * Time-to-refresh window in milliseconds. When the session is
20
+ * within `refreshAheadMs` of expiry the provider triggers a
21
+ * refresh on the next request. Defaults to 5 minutes.
22
+ */
23
+ readonly refreshAheadMs?: number;
24
+ /** Optional per-request `AbortSignal` (forwarded to refresh). */
25
+ readonly signal?: AbortSignal;
26
+ }
27
+ /**
28
+ * Live authorization-header provider returned by
29
+ * {@link createOAuthAuthorizationProvider}.
30
+ *
31
+ * @stable
32
+ */
33
+ interface OAuthAuthorizationProvider {
34
+ /** Resolve an `Authorization: Bearer ...` header. */
35
+ resolveHeader(): Promise<string>;
36
+ /** Force a refresh, regardless of expiry. */
37
+ refresh(): Promise<OAuthSession>;
38
+ /** Persist the most recently observed expiry timestamp. */
39
+ readonly serverId: string;
40
+ }
41
+ /**
42
+ * Build a provider that resolves the `Authorization` header value the
43
+ * Streamable HTTP / SSE MCP transports send on every request.
44
+ *
45
+ * The provider:
46
+ *
47
+ * 1. Loads the persisted session metadata from the supplied store.
48
+ * 2. Refreshes the session when it is within `refreshAheadMs` of
49
+ * expiry.
50
+ * 3. Wraps every refresh failure in {@link MCPAuthError} carrying a
51
+ * `hint` that points the operator to the upcoming
52
+ * `graphorin auth refresh` CLI.
53
+ *
54
+ * @stable
55
+ */
56
+ declare function createOAuthAuthorizationProvider(options: OAuthAuthorizationProviderOptions): OAuthAuthorizationProvider;
57
+ //#endregion
58
+ export { OAuthAuthorizationProvider, OAuthAuthorizationProviderOptions, createOAuthAuthorizationProvider };
59
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.ts","names":[],"sources":["../../src/oauth/bridge.ts"],"sourcesContent":[],"mappings":";;;;;;;AA0EgB,UAlDC,iCAAA,CAmDN;;;;;0BAnDuC,0BAAA,CAKY;;;;oBAI1C;;;;;;;;oBAQA;;;;;;;;UASH,0BAAA;;mBAEE;;aAEN,QAAQ;;;;;;;;;;;;;;;;;;;iBAoBL,gCAAA,UACL,oCACR"}
@@ -0,0 +1,75 @@
1
+ import { MCPAuthError } from "../errors/index.js";
2
+ import { GraphorinOAuthError, emitOAuthLifecycle, refreshOAuthSession } from "@graphorin/security/oauth";
3
+
4
+ //#region src/oauth/bridge.ts
5
+ /**
6
+ * Build a provider that resolves the `Authorization` header value the
7
+ * Streamable HTTP / SSE MCP transports send on every request.
8
+ *
9
+ * The provider:
10
+ *
11
+ * 1. Loads the persisted session metadata from the supplied store.
12
+ * 2. Refreshes the session when it is within `refreshAheadMs` of
13
+ * expiry.
14
+ * 3. Wraps every refresh failure in {@link MCPAuthError} carrying a
15
+ * `hint` that points the operator to the upcoming
16
+ * `graphorin auth refresh` CLI.
17
+ *
18
+ * @stable
19
+ */
20
+ function createOAuthAuthorizationProvider(options) {
21
+ const refreshAheadMs = options.refreshAheadMs ?? 5 * 6e4;
22
+ let activeSession;
23
+ async function loadOrRefresh(force) {
24
+ const record = await options.storage.get(options.serverId);
25
+ if (record === null) throw new MCPAuthError(`OAuth server '${options.serverId}' is not registered.`, {
26
+ hint: `run 'graphorin auth login --mcp ${options.serverId} --url <server-url>' to register the OAuth server.`,
27
+ metadata: { server: options.serverId }
28
+ });
29
+ const expiresAt = record.expiresAt;
30
+ if (!(force || activeSession === void 0 || expiresAt !== void 0 && expiresAt - Date.now() < refreshAheadMs) && activeSession !== void 0) return activeSession;
31
+ try {
32
+ const session = await refreshOAuthSession(options.storage, options.serverId, {
33
+ ...options.signal === void 0 ? {} : { signal: options.signal },
34
+ ...options.secretsStore === void 0 ? {} : { secretsStore: options.secretsStore }
35
+ });
36
+ activeSession = session;
37
+ return session;
38
+ } catch (cause) {
39
+ if (cause instanceof GraphorinOAuthError) {
40
+ emitOAuthLifecycle({
41
+ type: "mcp.auth.expired",
42
+ serverId: options.serverId,
43
+ ts: Date.now(),
44
+ reason: cause.kind,
45
+ metadata: { serverUrl: record.serverUrl }
46
+ });
47
+ throw new MCPAuthError(`MCP OAuth session for '${options.serverId}' could not be refreshed: ${cause.message}`, {
48
+ hint: `run 'graphorin auth refresh --mcp ${options.serverId}' to recover.`,
49
+ metadata: { server: options.serverId },
50
+ cause
51
+ });
52
+ }
53
+ throw new MCPAuthError(`MCP OAuth session for '${options.serverId}' could not be refreshed.`, {
54
+ hint: `run 'graphorin auth refresh --mcp ${options.serverId}' to recover.`,
55
+ metadata: { server: options.serverId },
56
+ cause
57
+ });
58
+ }
59
+ }
60
+ return Object.freeze({
61
+ serverId: options.serverId,
62
+ async resolveHeader() {
63
+ const session = await loadOrRefresh(false);
64
+ const tokenType = session.tokenType.length === 0 ? "Bearer" : session.tokenType;
65
+ return session.accessToken.use((raw) => `${tokenType} ${raw}`);
66
+ },
67
+ async refresh() {
68
+ return loadOrRefresh(true);
69
+ }
70
+ });
71
+ }
72
+
73
+ //#endregion
74
+ export { createOAuthAuthorizationProvider };
75
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","names":["activeSession: OAuthSession | undefined"],"sources":["../../src/oauth/bridge.ts"],"sourcesContent":["/**\n * Bridge between the MCP transport's bearer-token requirement and the\n * outbound OAuth subsystem in `@graphorin/security/oauth`.\n *\n * The bridge resolves an authorization header from a stored\n * {@link OAuthSession}, refreshes the token automatically when it is\n * within the configured pre-expiry window, and surfaces every\n * lifecycle transition (`oauth.granted` / `oauth.refreshed` /\n * `oauth.revoked` / `mcp.auth.expired`) to subscribers.\n *\n * @packageDocumentation\n */\n\nimport type { OAuthServerStore } from '@graphorin/core/contracts';\nimport type { OAuthSession } from '@graphorin/security/oauth';\nimport {\n emitOAuthLifecycle,\n GraphorinOAuthError,\n refreshOAuthSession,\n} from '@graphorin/security/oauth';\n\nimport { MCPAuthError } from '../errors/index.js';\n\n/** Options accepted by {@link createOAuthAuthorizationProvider}. */\nexport interface OAuthAuthorizationProviderOptions {\n /**\n * Secrets store the persisted tokens resolve from (SPL-1) — with it,\n * the bridge issues Authorization headers across process restarts.\n */\n readonly secretsStore?: import('@graphorin/core/contracts').SecretsStore;\n /** Stable identifier of the persisted OAuth server (`serverId`). */\n readonly serverId: string;\n /** Persistent storage. */\n readonly storage: OAuthServerStore;\n /**\n * Time-to-refresh window in milliseconds. When the session is\n * within `refreshAheadMs` of expiry the provider triggers a\n * refresh on the next request. Defaults to 5 minutes.\n */\n readonly refreshAheadMs?: number;\n /** Optional per-request `AbortSignal` (forwarded to refresh). */\n readonly signal?: AbortSignal;\n}\n\n/**\n * Live authorization-header provider returned by\n * {@link createOAuthAuthorizationProvider}.\n *\n * @stable\n */\nexport interface OAuthAuthorizationProvider {\n /** Resolve an `Authorization: Bearer ...` header. */\n resolveHeader(): Promise<string>;\n /** Force a refresh, regardless of expiry. */\n refresh(): Promise<OAuthSession>;\n /** Persist the most recently observed expiry timestamp. */\n readonly serverId: string;\n}\n\n/**\n * Build a provider that resolves the `Authorization` header value the\n * Streamable HTTP / SSE MCP transports send on every request.\n *\n * The provider:\n *\n * 1. Loads the persisted session metadata from the supplied store.\n * 2. Refreshes the session when it is within `refreshAheadMs` of\n * expiry.\n * 3. Wraps every refresh failure in {@link MCPAuthError} carrying a\n * `hint` that points the operator to the upcoming\n * `graphorin auth refresh` CLI.\n *\n * @stable\n */\nexport function createOAuthAuthorizationProvider(\n options: OAuthAuthorizationProviderOptions,\n): OAuthAuthorizationProvider {\n const refreshAheadMs = options.refreshAheadMs ?? 5 * 60_000;\n let activeSession: OAuthSession | undefined;\n\n async function loadOrRefresh(force: boolean): Promise<OAuthSession> {\n const record = await options.storage.get(options.serverId);\n if (record === null) {\n throw new MCPAuthError(`OAuth server '${options.serverId}' is not registered.`, {\n hint: `run 'graphorin auth login --mcp ${options.serverId} --url <server-url>' to register the OAuth server.`,\n metadata: { server: options.serverId },\n });\n }\n const expiresAt = record.expiresAt;\n const now = Date.now();\n const stale =\n force ||\n activeSession === undefined ||\n (expiresAt !== undefined && expiresAt - now < refreshAheadMs);\n if (!stale && activeSession !== undefined) return activeSession;\n try {\n const session = await refreshOAuthSession(options.storage, options.serverId, {\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n ...(options.secretsStore === undefined ? {} : { secretsStore: options.secretsStore }),\n });\n activeSession = session;\n return session;\n } catch (cause) {\n if (cause instanceof GraphorinOAuthError) {\n emitOAuthLifecycle({\n type: 'mcp.auth.expired',\n serverId: options.serverId,\n ts: Date.now(),\n reason: cause.kind,\n metadata: { serverUrl: record.serverUrl },\n });\n throw new MCPAuthError(\n `MCP OAuth session for '${options.serverId}' could not be refreshed: ${cause.message}`,\n {\n hint: `run 'graphorin auth refresh --mcp ${options.serverId}' to recover.`,\n metadata: { server: options.serverId },\n cause,\n },\n );\n }\n throw new MCPAuthError(\n `MCP OAuth session for '${options.serverId}' could not be refreshed.`,\n {\n hint: `run 'graphorin auth refresh --mcp ${options.serverId}' to recover.`,\n metadata: { server: options.serverId },\n cause,\n },\n );\n }\n }\n\n return Object.freeze({\n serverId: options.serverId,\n async resolveHeader(): Promise<string> {\n const session = await loadOrRefresh(false);\n const tokenType = session.tokenType.length === 0 ? 'Bearer' : session.tokenType;\n return session.accessToken.use((raw) => `${tokenType} ${raw}`);\n },\n async refresh(): Promise<OAuthSession> {\n return loadOrRefresh(true);\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA0EA,SAAgB,iCACd,SAC4B;CAC5B,MAAM,iBAAiB,QAAQ,kBAAkB,IAAI;CACrD,IAAIA;CAEJ,eAAe,cAAc,OAAuC;EAClE,MAAM,SAAS,MAAM,QAAQ,QAAQ,IAAI,QAAQ,SAAS;AAC1D,MAAI,WAAW,KACb,OAAM,IAAI,aAAa,iBAAiB,QAAQ,SAAS,uBAAuB;GAC9E,MAAM,mCAAmC,QAAQ,SAAS;GAC1D,UAAU,EAAE,QAAQ,QAAQ,UAAU;GACvC,CAAC;EAEJ,MAAM,YAAY,OAAO;AAMzB,MAAI,EAHF,SACA,kBAAkB,UACjB,cAAc,UAAa,YAJlB,KAAK,KAAK,GAI0B,mBAClC,kBAAkB,OAAW,QAAO;AAClD,MAAI;GACF,MAAM,UAAU,MAAM,oBAAoB,QAAQ,SAAS,QAAQ,UAAU;IAC3E,GAAI,QAAQ,WAAW,SAAY,EAAE,GAAG,EAAE,QAAQ,QAAQ,QAAQ;IAClE,GAAI,QAAQ,iBAAiB,SAAY,EAAE,GAAG,EAAE,cAAc,QAAQ,cAAc;IACrF,CAAC;AACF,mBAAgB;AAChB,UAAO;WACA,OAAO;AACd,OAAI,iBAAiB,qBAAqB;AACxC,uBAAmB;KACjB,MAAM;KACN,UAAU,QAAQ;KAClB,IAAI,KAAK,KAAK;KACd,QAAQ,MAAM;KACd,UAAU,EAAE,WAAW,OAAO,WAAW;KAC1C,CAAC;AACF,UAAM,IAAI,aACR,0BAA0B,QAAQ,SAAS,4BAA4B,MAAM,WAC7E;KACE,MAAM,qCAAqC,QAAQ,SAAS;KAC5D,UAAU,EAAE,QAAQ,QAAQ,UAAU;KACtC;KACD,CACF;;AAEH,SAAM,IAAI,aACR,0BAA0B,QAAQ,SAAS,4BAC3C;IACE,MAAM,qCAAqC,QAAQ,SAAS;IAC5D,UAAU,EAAE,QAAQ,QAAQ,UAAU;IACtC;IACD,CACF;;;AAIL,QAAO,OAAO,OAAO;EACnB,UAAU,QAAQ;EAClB,MAAM,gBAAiC;GACrC,MAAM,UAAU,MAAM,cAAc,MAAM;GAC1C,MAAM,YAAY,QAAQ,UAAU,WAAW,IAAI,WAAW,QAAQ;AACtE,UAAO,QAAQ,YAAY,KAAK,QAAQ,GAAG,UAAU,GAAG,MAAM;;EAEhE,MAAM,UAAiC;AACrC,UAAO,cAAc,KAAK;;EAE7B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { OAuthAuthorizationProvider, OAuthAuthorizationProviderOptions, createOAuthAuthorizationProvider } from "./bridge.js";
2
+ import { mcpAuthListSessions, mcpAuthLogin, mcpAuthRefresh, mcpAuthRevoke, mcpAuthStatus } from "./library.js";
3
+ export { type OAuthAuthorizationProvider, type OAuthAuthorizationProviderOptions, createOAuthAuthorizationProvider, mcpAuthListSessions, mcpAuthLogin, mcpAuthRefresh, mcpAuthRevoke, mcpAuthStatus };
@@ -0,0 +1,4 @@
1
+ import { createOAuthAuthorizationProvider } from "./bridge.js";
2
+ import { mcpAuthListSessions, mcpAuthLogin, mcpAuthRefresh, mcpAuthRevoke, mcpAuthStatus } from "./library.js";
3
+
4
+ export { createOAuthAuthorizationProvider, mcpAuthListSessions, mcpAuthLogin, mcpAuthRefresh, mcpAuthRevoke, mcpAuthStatus };
@@ -0,0 +1,23 @@
1
+ import { LoginInteractiveOptions, LoginInteractiveResult, OAuthSession, OAuthSessionMetadata, OAuthStatusSnapshot } from "@graphorin/security/oauth";
2
+ import { OAuthServerStore } from "@graphorin/core/contracts";
3
+
4
+ //#region src/oauth/library.d.ts
5
+
6
+ /** Drive `graphorin auth login --mcp <id>`. */
7
+ declare function mcpAuthLogin(options: LoginInteractiveOptions): Promise<LoginInteractiveResult>;
8
+ /** Drive `graphorin auth list --mcp`. */
9
+ declare function mcpAuthListSessions(storage: OAuthServerStore): Promise<ReadonlyArray<OAuthSessionMetadata>>;
10
+ /** Drive `graphorin auth refresh --mcp <id>`. */
11
+ declare function mcpAuthRefresh(storage: OAuthServerStore, serverId: string, options?: {
12
+ readonly signal?: AbortSignal;
13
+ }): Promise<OAuthSession>;
14
+ /** Drive `graphorin auth revoke --mcp <id>`. */
15
+ declare function mcpAuthRevoke(storage: OAuthServerStore, serverId: string, options?: {
16
+ readonly reason?: string;
17
+ readonly signal?: AbortSignal;
18
+ }): Promise<void>;
19
+ /** Drive `graphorin auth status --mcp`. */
20
+ declare function mcpAuthStatus(storage: OAuthServerStore): Promise<OAuthStatusSnapshot>;
21
+ //#endregion
22
+ export { mcpAuthListSessions, mcpAuthLogin, mcpAuthRefresh, mcpAuthRevoke, mcpAuthStatus };
23
+ //# sourceMappingURL=library.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"library.d.ts","names":[],"sources":["../../src/oauth/library.ts"],"sourcesContent":[],"mappings":";;;;;;AAmCG,iBATmB,YAAA,CASnB,OAAA,EARQ,uBAQR,CAAA,EAPA,OAOA,CAPQ,sBAOR,CAAA;;AAKmB,iBAPA,mBAAA,CAOc,OAAA,EANzB,gBAMyB,CAAA,EALjC,OAKiC,CALzB,aAKyB,CALX,oBAKW,CAAA,CAAA;;AAGL,iBAHT,cAAA,CAGS,OAAA,EAFpB,gBAEoB,EAAA,QAAA,EAAA,MAAA,EAAA,OAC5B,CAD4B,EAAA;EACpB,SAAA,MAAA,CAAA,EADoB,WACpB;CAAR,CAAA,EAAA,OAAA,CAAQ,YAAR,CAAA;;AAKmB,iBAAA,aAAA,CAAa,OAAA,EACxB,gBADwB,EAAA,QAAA,EAAA,MAAA,EAAA,OAIhC,CAJgC,EAAA;EACxB,SAAA,MAAA,CAAA,EAAA,MAAA;EAE8C,SAAA,MAAA,CAAA,EAAA,WAAA;CACtD,CAAA,EAAA,OAAA,CAAA,IAAA,CAAA;;AAKmB,iBAAA,aAAA,CAAa,OAAA,EAAU,gBAAV,CAAA,EAA6B,OAA7B,CAAqC,mBAArC,CAAA"}
@@ -0,0 +1,27 @@
1
+ import { getOAuthStatus, listOAuthSessions, loginInteractive, refreshOAuthSession, revokeOAuthSession } from "@graphorin/security/oauth";
2
+
3
+ //#region src/oauth/library.ts
4
+ /** Drive `graphorin auth login --mcp <id>`. */
5
+ async function mcpAuthLogin(options) {
6
+ return loginInteractive(options);
7
+ }
8
+ /** Drive `graphorin auth list --mcp`. */
9
+ async function mcpAuthListSessions(storage) {
10
+ return listOAuthSessions(storage);
11
+ }
12
+ /** Drive `graphorin auth refresh --mcp <id>`. */
13
+ async function mcpAuthRefresh(storage, serverId, options = {}) {
14
+ return refreshOAuthSession(storage, serverId, options);
15
+ }
16
+ /** Drive `graphorin auth revoke --mcp <id>`. */
17
+ async function mcpAuthRevoke(storage, serverId, options = {}) {
18
+ await revokeOAuthSession(storage, serverId, options);
19
+ }
20
+ /** Drive `graphorin auth status --mcp`. */
21
+ async function mcpAuthStatus(storage) {
22
+ return getOAuthStatus(storage);
23
+ }
24
+
25
+ //#endregion
26
+ export { mcpAuthListSessions, mcpAuthLogin, mcpAuthRefresh, mcpAuthRevoke, mcpAuthStatus };
27
+ //# sourceMappingURL=library.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"library.js","names":[],"sources":["../../src/oauth/library.ts"],"sourcesContent":["/**\n * Thin re-export wrappers for the OAuth library functions consumed by\n * the upcoming `graphorin auth login | list | refresh | revoke |\n * status` CLI surface (Phase 15). The wrappers attach an\n * `mcpServerId` audit tag so downstream observers can attribute\n * events to the MCP subsystem rather than to a generic OAuth call\n * site.\n *\n * @packageDocumentation\n */\n\nimport type { OAuthServerStore } from '@graphorin/core/contracts';\nimport {\n getOAuthStatus,\n type LoginInteractiveOptions,\n type LoginInteractiveResult,\n listOAuthSessions,\n loginInteractive,\n type OAuthSession,\n type OAuthSessionMetadata,\n type OAuthStatusSnapshot,\n refreshOAuthSession,\n revokeOAuthSession,\n} from '@graphorin/security/oauth';\n\n/** Drive `graphorin auth login --mcp <id>`. */\nexport async function mcpAuthLogin(\n options: LoginInteractiveOptions,\n): Promise<LoginInteractiveResult> {\n return loginInteractive(options);\n}\n\n/** Drive `graphorin auth list --mcp`. */\nexport async function mcpAuthListSessions(\n storage: OAuthServerStore,\n): Promise<ReadonlyArray<OAuthSessionMetadata>> {\n return listOAuthSessions(storage);\n}\n\n/** Drive `graphorin auth refresh --mcp <id>`. */\nexport async function mcpAuthRefresh(\n storage: OAuthServerStore,\n serverId: string,\n options: { readonly signal?: AbortSignal } = {},\n): Promise<OAuthSession> {\n return refreshOAuthSession(storage, serverId, options);\n}\n\n/** Drive `graphorin auth revoke --mcp <id>`. */\nexport async function mcpAuthRevoke(\n storage: OAuthServerStore,\n serverId: string,\n options: { readonly reason?: string; readonly signal?: AbortSignal } = {},\n): Promise<void> {\n await revokeOAuthSession(storage, serverId, options);\n}\n\n/** Drive `graphorin auth status --mcp`. */\nexport async function mcpAuthStatus(storage: OAuthServerStore): Promise<OAuthStatusSnapshot> {\n return getOAuthStatus(storage);\n}\n"],"mappings":";;;;AA0BA,eAAsB,aACpB,SACiC;AACjC,QAAO,iBAAiB,QAAQ;;;AAIlC,eAAsB,oBACpB,SAC8C;AAC9C,QAAO,kBAAkB,QAAQ;;;AAInC,eAAsB,eACpB,SACA,UACA,UAA6C,EAAE,EACxB;AACvB,QAAO,oBAAoB,SAAS,UAAU,QAAQ;;;AAIxD,eAAsB,cACpB,SACA,UACA,UAAuE,EAAE,EAC1D;AACf,OAAM,mBAAmB,SAAS,UAAU,QAAQ;;;AAItD,eAAsB,cAAc,SAAyD;AAC3F,QAAO,eAAe,QAAQ"}