@phake/mcp 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +187 -0
- package/dist/adapters/http-node/http/app.d.ts +5 -0
- package/dist/adapters/http-node/http/auth-app.d.ts +5 -0
- package/dist/adapters/http-node/http/middlewares/auth.d.ts +39 -0
- package/dist/adapters/http-node/http/middlewares/cors.d.ts +8 -0
- package/dist/adapters/http-node/http/routes/health.d.ts +5 -0
- package/dist/adapters/http-node/http/routes/mcp.d.ts +11 -0
- package/dist/adapters/http-node/middleware.security.d.ts +6 -0
- package/dist/adapters/http-node/routes.discovery.d.ts +6 -0
- package/dist/adapters/http-node/routes.oauth.d.ts +7 -0
- package/dist/adapters/http-worker/index.d.ts +48 -0
- package/dist/adapters/http-worker/mcp.handler.d.ts +24 -0
- package/dist/adapters/http-worker/routes.discovery.d.ts +7 -0
- package/dist/adapters/http-worker/routes.oauth.d.ts +8 -0
- package/dist/adapters/http-worker/security.d.ts +7 -0
- package/dist/index-1zyem3xr.js +14893 -0
- package/dist/index-4f4xvtt9.js +19552 -0
- package/dist/index-sbqy8kgq.js +3478 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +1083 -0
- package/dist/mcp-server.d.ts +18 -0
- package/dist/runtime/node/capabilities.d.ts +2 -0
- package/dist/runtime/node/context.d.ts +29 -0
- package/dist/runtime/node/index.d.ts +5 -0
- package/dist/runtime/node/index.js +27 -0
- package/dist/runtime/node/mcp.d.ts +28 -0
- package/dist/runtime/node/storage/file.d.ts +44 -0
- package/dist/runtime/node/storage/sqlite.d.ts +213 -0
- package/dist/runtime/worker/index.d.ts +1 -0
- package/dist/runtime/worker/index.js +12 -0
- package/dist/shared/auth/index.d.ts +1 -0
- package/dist/shared/auth/strategy.d.ts +71 -0
- package/dist/shared/config/env.d.ts +52 -0
- package/dist/shared/config/index.d.ts +2 -0
- package/dist/shared/config/metadata.d.ts +5 -0
- package/dist/shared/crypto/aes-gcm.d.ts +37 -0
- package/dist/shared/crypto/index.d.ts +1 -0
- package/dist/shared/http/cors.d.ts +20 -0
- package/dist/shared/http/index.d.ts +2 -0
- package/dist/shared/http/response.d.ts +52 -0
- package/dist/shared/mcp/dispatcher.d.ts +81 -0
- package/dist/shared/mcp/index.d.ts +3 -0
- package/dist/shared/mcp/security.d.ts +23 -0
- package/dist/shared/mcp/server-internals.d.ts +79 -0
- package/dist/shared/oauth/cimd.d.ts +43 -0
- package/dist/shared/oauth/discovery-handlers.d.ts +14 -0
- package/dist/shared/oauth/discovery.d.ts +26 -0
- package/dist/shared/oauth/endpoints.d.ts +11 -0
- package/dist/shared/oauth/flow.d.ts +31 -0
- package/dist/shared/oauth/index.d.ts +9 -0
- package/dist/shared/oauth/input-parsers.d.ts +43 -0
- package/dist/shared/oauth/refresh.d.ts +61 -0
- package/dist/shared/oauth/ssrf.d.ts +31 -0
- package/dist/shared/oauth/types.d.ts +78 -0
- package/dist/shared/schemas/prompts.d.ts +1 -0
- package/dist/shared/services/http-client.d.ts +16 -0
- package/dist/shared/services/index.d.ts +1 -0
- package/dist/shared/storage/index.d.ts +4 -0
- package/dist/shared/storage/interface.d.ts +99 -0
- package/dist/shared/storage/kv.d.ts +68 -0
- package/dist/shared/storage/memory.d.ts +91 -0
- package/dist/shared/storage/singleton.d.ts +4 -0
- package/dist/shared/tools/echo.d.ts +16 -0
- package/dist/shared/tools/health.d.ts +13 -0
- package/dist/shared/tools/index.d.ts +4 -0
- package/dist/shared/tools/registry.d.ts +64 -0
- package/dist/shared/tools/types.d.ts +161 -0
- package/dist/shared/types/auth.d.ts +35 -0
- package/dist/shared/types/context.d.ts +79 -0
- package/dist/shared/types/index.d.ts +8 -0
- package/dist/shared/types/provider.d.ts +28 -0
- package/dist/shared/utils/base64.d.ts +12 -0
- package/dist/shared/utils/cancellation.d.ts +13 -0
- package/dist/shared/utils/elicitation.d.ts +247 -0
- package/dist/shared/utils/formatting.d.ts +106 -0
- package/dist/shared/utils/index.d.ts +11 -0
- package/dist/shared/utils/limits.d.ts +6 -0
- package/dist/shared/utils/logger.d.ts +20 -0
- package/dist/shared/utils/pagination.d.ts +11 -0
- package/dist/shared/utils/progress.d.ts +56 -0
- package/dist/shared/utils/roots.d.ts +62 -0
- package/dist/shared/utils/sampling.d.ts +155 -0
- package/dist/shared/utils/security.d.ts +6 -0
- package/package.json +55 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared MCP JSON-RPC dispatcher.
|
|
3
|
+
* Used by both Node.js (via SDK wrapper) and Cloudflare Workers (directly).
|
|
4
|
+
*/
|
|
5
|
+
import type { ToolContext } from "../tools/types.js";
|
|
6
|
+
export declare const LATEST_PROTOCOL_VERSION = "2025-06-18";
|
|
7
|
+
export declare const SUPPORTED_PROTOCOL_VERSIONS: string[];
|
|
8
|
+
/** JSON-RPC error codes */
|
|
9
|
+
export declare const JsonRpcErrorCode: {
|
|
10
|
+
readonly ParseError: -32700;
|
|
11
|
+
readonly InvalidRequest: -32600;
|
|
12
|
+
readonly MethodNotFound: -32601;
|
|
13
|
+
readonly InvalidParams: -32602;
|
|
14
|
+
readonly InternalError: -32603;
|
|
15
|
+
};
|
|
16
|
+
/** MCP server configuration */
|
|
17
|
+
export interface McpServerConfig {
|
|
18
|
+
title: string;
|
|
19
|
+
version: string;
|
|
20
|
+
instructions?: string;
|
|
21
|
+
}
|
|
22
|
+
/** Session state for MCP connections */
|
|
23
|
+
export interface McpSessionState {
|
|
24
|
+
initialized: boolean;
|
|
25
|
+
clientInfo?: {
|
|
26
|
+
name: string;
|
|
27
|
+
version: string;
|
|
28
|
+
};
|
|
29
|
+
protocolVersion?: string;
|
|
30
|
+
}
|
|
31
|
+
/** Cancellation controller registry for in-flight requests */
|
|
32
|
+
export type CancellationRegistry = Map<string | number, AbortController>;
|
|
33
|
+
/** Context for MCP request handling */
|
|
34
|
+
export interface McpDispatchContext {
|
|
35
|
+
sessionId: string;
|
|
36
|
+
auth: ToolContext;
|
|
37
|
+
config: McpServerConfig;
|
|
38
|
+
getSessionState: () => McpSessionState | undefined;
|
|
39
|
+
setSessionState: (state: McpSessionState) => void;
|
|
40
|
+
/** Registry for tracking in-flight requests that can be cancelled */
|
|
41
|
+
cancellationRegistry?: CancellationRegistry;
|
|
42
|
+
/** Custom tools (if not provided, uses sharedTools) */
|
|
43
|
+
tools?: import("../tools/types.js").SharedToolDefinition[];
|
|
44
|
+
}
|
|
45
|
+
/** JSON-RPC response */
|
|
46
|
+
export interface JsonRpcResult {
|
|
47
|
+
result?: unknown;
|
|
48
|
+
error?: {
|
|
49
|
+
code: number;
|
|
50
|
+
message: string;
|
|
51
|
+
data?: unknown;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get the current log level set by the client.
|
|
56
|
+
*/
|
|
57
|
+
export declare function getLogLevel(): string;
|
|
58
|
+
/**
|
|
59
|
+
* Dispatch an MCP JSON-RPC method.
|
|
60
|
+
*
|
|
61
|
+
* @param method - The JSON-RPC method name
|
|
62
|
+
* @param params - The method parameters
|
|
63
|
+
* @param ctx - Dispatch context with session and auth info
|
|
64
|
+
* @param requestId - Optional request ID for cancellation tracking
|
|
65
|
+
* @returns JSON-RPC result or error
|
|
66
|
+
*/
|
|
67
|
+
export declare function dispatchMcpMethod(method: string | undefined, params: Record<string, unknown> | undefined, ctx: McpDispatchContext, requestId?: string | number): Promise<JsonRpcResult>;
|
|
68
|
+
/** Parameters for notifications/cancelled */
|
|
69
|
+
export interface CancelledNotificationParams {
|
|
70
|
+
requestId: string | number;
|
|
71
|
+
reason?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Handle MCP notification (no response expected).
|
|
75
|
+
*
|
|
76
|
+
* @param method - The notification method name
|
|
77
|
+
* @param params - Notification parameters
|
|
78
|
+
* @param ctx - Dispatch context
|
|
79
|
+
* @returns true if handled, false if unknown
|
|
80
|
+
*/
|
|
81
|
+
export declare function handleMcpNotification(method: string, params: Record<string, unknown> | undefined, ctx: McpDispatchContext): boolean;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare function validateOrigin(headers: Headers, isDev: boolean): void;
|
|
2
|
+
export declare function validateProtocolVersion(headers: Headers, _expected: string): void;
|
|
3
|
+
export type UnauthorizedChallenge = {
|
|
4
|
+
status: 401;
|
|
5
|
+
headers: Record<string, string>;
|
|
6
|
+
body: {
|
|
7
|
+
jsonrpc: "2.0";
|
|
8
|
+
error: {
|
|
9
|
+
code: -32000;
|
|
10
|
+
message: string;
|
|
11
|
+
};
|
|
12
|
+
id: null;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Build a 401 Unauthorized challenge response for MCP
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildUnauthorizedChallenge(args: {
|
|
19
|
+
origin: string;
|
|
20
|
+
sid: string;
|
|
21
|
+
resourcePath?: string;
|
|
22
|
+
message?: string;
|
|
23
|
+
}): UnauthorizedChallenge;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe access to internal MCP SDK Server properties.
|
|
3
|
+
*
|
|
4
|
+
* The McpServer class wraps a lower-level Server instance that provides
|
|
5
|
+
* direct access to request/notification methods and client capabilities.
|
|
6
|
+
* This module provides typed helpers to access these internals safely.
|
|
7
|
+
*/
|
|
8
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9
|
+
/**
|
|
10
|
+
* Shape of the internal server with commonly used methods.
|
|
11
|
+
* These are not part of the public McpServer API but are needed
|
|
12
|
+
* for advanced features like client requests and capability checks.
|
|
13
|
+
*/
|
|
14
|
+
interface LowLevelServer {
|
|
15
|
+
request?: (params: {
|
|
16
|
+
method: string;
|
|
17
|
+
params?: unknown;
|
|
18
|
+
}, schema?: {
|
|
19
|
+
parse: (r: unknown) => unknown;
|
|
20
|
+
}) => Promise<unknown>;
|
|
21
|
+
notification?: (params: {
|
|
22
|
+
method: string;
|
|
23
|
+
params?: unknown;
|
|
24
|
+
}) => Promise<void>;
|
|
25
|
+
setRequestHandler?: (method: string, handler: (request: unknown) => Promise<unknown>) => void;
|
|
26
|
+
getClientCapabilities?: () => ClientCapabilities;
|
|
27
|
+
getClientVersion?: () => string;
|
|
28
|
+
oninitialized?: () => void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Client capabilities shape for type-safe access.
|
|
32
|
+
*/
|
|
33
|
+
interface ClientCapabilities {
|
|
34
|
+
roots?: {
|
|
35
|
+
listChanged?: boolean;
|
|
36
|
+
};
|
|
37
|
+
sampling?: {
|
|
38
|
+
tools?: boolean;
|
|
39
|
+
};
|
|
40
|
+
elicitation?: {
|
|
41
|
+
form?: unknown;
|
|
42
|
+
url?: boolean;
|
|
43
|
+
};
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* McpServer with internal methods typed (use with type assertion).
|
|
48
|
+
*/
|
|
49
|
+
interface McpServerWithInternals {
|
|
50
|
+
server?: LowLevelServer;
|
|
51
|
+
sendResourceUpdated?: (params: {
|
|
52
|
+
uri: string;
|
|
53
|
+
}) => void;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get the low-level server instance from McpServer.
|
|
57
|
+
* Returns the internal Server or falls back to the McpServer itself.
|
|
58
|
+
*/
|
|
59
|
+
export declare function getLowLevelServer(server: McpServer): LowLevelServer;
|
|
60
|
+
/**
|
|
61
|
+
* Get McpServer with internal methods typed.
|
|
62
|
+
*/
|
|
63
|
+
export declare function getServerWithInternals(server: McpServer): McpServerWithInternals;
|
|
64
|
+
/**
|
|
65
|
+
* JSON-RPC error with code property.
|
|
66
|
+
*/
|
|
67
|
+
export interface JsonRpcError extends Error {
|
|
68
|
+
code?: number;
|
|
69
|
+
data?: unknown;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if an error is a JSON-RPC error with a specific code.
|
|
73
|
+
*/
|
|
74
|
+
export declare function isJsonRpcError(error: unknown, code?: number): error is JsonRpcError;
|
|
75
|
+
/**
|
|
76
|
+
* JSON-RPC error code for method not found.
|
|
77
|
+
*/
|
|
78
|
+
export declare const JSON_RPC_METHOD_NOT_FOUND = -32601;
|
|
79
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Client metadata document schema (RFC 7591 compatible)
|
|
4
|
+
*/
|
|
5
|
+
export declare const ClientMetadataSchema: z.ZodObject<{
|
|
6
|
+
client_id: z.ZodString;
|
|
7
|
+
client_name: z.ZodOptional<z.ZodString>;
|
|
8
|
+
redirect_uris: z.ZodArray<z.ZodString>;
|
|
9
|
+
client_uri: z.ZodOptional<z.ZodString>;
|
|
10
|
+
logo_uri: z.ZodOptional<z.ZodString>;
|
|
11
|
+
tos_uri: z.ZodOptional<z.ZodString>;
|
|
12
|
+
policy_uri: z.ZodOptional<z.ZodString>;
|
|
13
|
+
jwks_uri: z.ZodOptional<z.ZodString>;
|
|
14
|
+
software_statement: z.ZodOptional<z.ZodString>;
|
|
15
|
+
}, z.core.$strip>;
|
|
16
|
+
export type ClientMetadata = z.infer<typeof ClientMetadataSchema>;
|
|
17
|
+
export type CimdConfig = {
|
|
18
|
+
/** Fetch timeout in milliseconds (default: 5000) */
|
|
19
|
+
timeoutMs?: number;
|
|
20
|
+
/** Maximum response size in bytes (default: 65536) */
|
|
21
|
+
maxBytes?: number;
|
|
22
|
+
/** List of allowed domains (if set, only these domains are allowed) */
|
|
23
|
+
allowedDomains?: string[];
|
|
24
|
+
};
|
|
25
|
+
export type CimdFetchResult = {
|
|
26
|
+
success: true;
|
|
27
|
+
metadata: ClientMetadata;
|
|
28
|
+
} | {
|
|
29
|
+
success: false;
|
|
30
|
+
error: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Check if a client_id is a CIMD URL (HTTPS with non-root path)
|
|
34
|
+
*/
|
|
35
|
+
export declare function isClientIdUrl(clientId: string): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Fetch and validate client metadata from a CIMD URL
|
|
38
|
+
*/
|
|
39
|
+
export declare function fetchClientMetadata(clientIdUrl: string, config?: CimdConfig): Promise<CimdFetchResult>;
|
|
40
|
+
/**
|
|
41
|
+
* Validate that a redirect_uri is allowed by the client metadata
|
|
42
|
+
*/
|
|
43
|
+
export declare function validateRedirectUri(metadata: ClientMetadata, redirectUri: string): boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { UnifiedConfig } from "../config/env.js";
|
|
2
|
+
import { buildAuthorizationServerMetadata, buildProtectedResourceMetadata } from "./discovery.js";
|
|
3
|
+
type DiscoveryStrategy = {
|
|
4
|
+
resolveAuthBaseUrl(requestUrl: URL, config: UnifiedConfig): string;
|
|
5
|
+
resolveAuthorizationServerUrl(requestUrl: URL, config: UnifiedConfig): string;
|
|
6
|
+
resolveResourceBaseUrl(requestUrl: URL, config: UnifiedConfig): string;
|
|
7
|
+
};
|
|
8
|
+
export declare function createDiscoveryHandlers(config: UnifiedConfig, strategy: DiscoveryStrategy): {
|
|
9
|
+
authorizationMetadata: (requestUrl: URL) => ReturnType<typeof buildAuthorizationServerMetadata>;
|
|
10
|
+
protectedResourceMetadata: (requestUrl: URL, sid?: string) => ReturnType<typeof buildProtectedResourceMetadata>;
|
|
11
|
+
};
|
|
12
|
+
export declare const workerDiscoveryStrategy: DiscoveryStrategy;
|
|
13
|
+
export declare const nodeDiscoveryStrategy: DiscoveryStrategy;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type AuthorizationServerMetadata = {
|
|
2
|
+
issuer: string;
|
|
3
|
+
authorization_endpoint: string;
|
|
4
|
+
token_endpoint: string;
|
|
5
|
+
revocation_endpoint: string;
|
|
6
|
+
registration_endpoint: string;
|
|
7
|
+
response_types_supported: string[];
|
|
8
|
+
grant_types_supported: string[];
|
|
9
|
+
code_challenge_methods_supported: string[];
|
|
10
|
+
token_endpoint_auth_methods_supported: string[];
|
|
11
|
+
scopes_supported: string[];
|
|
12
|
+
/** SEP-991: CIMD support flag */
|
|
13
|
+
client_id_metadata_document_supported?: boolean;
|
|
14
|
+
};
|
|
15
|
+
export type ProtectedResourceMetadata = {
|
|
16
|
+
authorization_servers: string[];
|
|
17
|
+
resource: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function buildAuthorizationServerMetadata(baseUrl: string, scopes: string[], overrides?: {
|
|
20
|
+
authorizationEndpoint?: string;
|
|
21
|
+
tokenEndpoint?: string;
|
|
22
|
+
revocationEndpoint?: string;
|
|
23
|
+
/** Enable CIMD support (SEP-991) */
|
|
24
|
+
cimdEnabled?: boolean;
|
|
25
|
+
}): AuthorizationServerMetadata;
|
|
26
|
+
export declare function buildProtectedResourceMetadata(resourceUrl: string, authorizationServerUrl: string, sid?: string): ProtectedResourceMetadata;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RegisterInput, RegisterResult } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Handle dynamic client registration (RFC7591)
|
|
4
|
+
*/
|
|
5
|
+
export declare function handleRegister(input: RegisterInput, baseUrl: string, defaultRedirectUri: string): Promise<RegisterResult>;
|
|
6
|
+
/**
|
|
7
|
+
* Handle token revocation (no-op in this implementation)
|
|
8
|
+
*/
|
|
9
|
+
export declare function handleRevoke(): Promise<{
|
|
10
|
+
status: string;
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { TokenStore } from "../storage/interface.js";
|
|
2
|
+
import { type CimdConfig } from "./cimd.js";
|
|
3
|
+
import type { AuthorizeInput, AuthorizeResult, CallbackInput, CallbackResult, OAuthConfig, ProviderConfig, TokenInput, TokenResult } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Generate a cryptographically secure opaque token.
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateOpaqueToken(bytes?: number): string;
|
|
8
|
+
/**
|
|
9
|
+
* Handle authorization request - redirect to provider or issue dev code
|
|
10
|
+
*/
|
|
11
|
+
export declare function handleAuthorize(input: AuthorizeInput, store: TokenStore, providerConfig: ProviderConfig, oauthConfig: OAuthConfig, options: {
|
|
12
|
+
baseUrl: string;
|
|
13
|
+
isDev: boolean;
|
|
14
|
+
callbackPath?: string;
|
|
15
|
+
/** CIMD configuration (SEP-991) */
|
|
16
|
+
cimd?: CimdConfig & {
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
};
|
|
19
|
+
}): Promise<AuthorizeResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Handle provider callback - exchange code for tokens using oauth4webapi
|
|
22
|
+
*/
|
|
23
|
+
export declare function handleProviderCallback(input: CallbackInput, store: TokenStore, providerConfig: ProviderConfig, oauthConfig: OAuthConfig, options: {
|
|
24
|
+
baseUrl: string;
|
|
25
|
+
isDev: boolean;
|
|
26
|
+
callbackPath?: string;
|
|
27
|
+
}): Promise<CallbackResult>;
|
|
28
|
+
/**
|
|
29
|
+
* Handle token exchange (authorization_code or refresh_token grant)
|
|
30
|
+
*/
|
|
31
|
+
export declare function handleToken(input: TokenInput, store: TokenStore, providerConfig?: ProviderConfig): Promise<TokenResult>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./cimd.js";
|
|
2
|
+
export * from "./discovery.js";
|
|
3
|
+
export * from "./discovery-handlers.js";
|
|
4
|
+
export * from "./endpoints.js";
|
|
5
|
+
export * from "./flow.js";
|
|
6
|
+
export * from "./input-parsers.js";
|
|
7
|
+
export * from "./refresh.js";
|
|
8
|
+
export * from "./ssrf.js";
|
|
9
|
+
export * from "./types.js";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { UnifiedConfig } from "../config/env.js";
|
|
2
|
+
import type { AuthorizeInput, OAuthConfig, ProviderConfig, TokenInput } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Parse authorization request from URL search params.
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseAuthorizeInput(url: URL, sessionId?: string): AuthorizeInput;
|
|
7
|
+
/**
|
|
8
|
+
* Parse callback request from URL search params.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseCallbackInput(url: URL): {
|
|
11
|
+
code: string | null;
|
|
12
|
+
state: string | null;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Parse token request from form data or JSON body.
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseTokenInput(request: Request): Promise<URLSearchParams>;
|
|
18
|
+
/**
|
|
19
|
+
* Build TokenInput from parsed form data.
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildTokenInput(form: URLSearchParams): TokenInput | {
|
|
22
|
+
error: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Build ProviderConfig from UnifiedConfig.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildProviderConfig(config: UnifiedConfig): ProviderConfig;
|
|
28
|
+
/**
|
|
29
|
+
* Build OAuthConfig from UnifiedConfig.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildOAuthConfig(config: UnifiedConfig): OAuthConfig;
|
|
32
|
+
/**
|
|
33
|
+
* Build flow options from request URL.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildFlowOptions(url: URL, config: UnifiedConfig, overrides?: {
|
|
36
|
+
callbackPath?: string;
|
|
37
|
+
tokenEndpointPath?: string;
|
|
38
|
+
}): {
|
|
39
|
+
baseUrl: string;
|
|
40
|
+
isDev: boolean;
|
|
41
|
+
callbackPath: string;
|
|
42
|
+
tokenEndpointPath: string;
|
|
43
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proactive token refresh utilities using oauth4webapi.
|
|
3
|
+
*
|
|
4
|
+
* This module provides token refresh functionality that can be used
|
|
5
|
+
* during tool execution to ensure tokens are fresh before making API calls.
|
|
6
|
+
*/
|
|
7
|
+
import type { ProviderTokens, TokenStore } from "../storage/interface.js";
|
|
8
|
+
/** Provider configuration for token refresh */
|
|
9
|
+
export interface ProviderRefreshConfig {
|
|
10
|
+
clientId: string;
|
|
11
|
+
clientSecret: string;
|
|
12
|
+
accountsUrl: string;
|
|
13
|
+
tokenEndpointPath?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Build provider refresh config from unified config.
|
|
17
|
+
* Returns undefined if required fields are missing.
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildProviderRefreshConfig(config: {
|
|
20
|
+
PROVIDER_CLIENT_ID?: string;
|
|
21
|
+
PROVIDER_CLIENT_SECRET?: string;
|
|
22
|
+
PROVIDER_ACCOUNTS_URL?: string;
|
|
23
|
+
OAUTH_TOKEN_URL?: string;
|
|
24
|
+
}): ProviderRefreshConfig | undefined;
|
|
25
|
+
/** Token refresh result */
|
|
26
|
+
export interface RefreshResult {
|
|
27
|
+
success: boolean;
|
|
28
|
+
tokens?: ProviderTokens;
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Refresh provider token using refresh_token grant via oauth4webapi.
|
|
33
|
+
*
|
|
34
|
+
* @param refreshToken - The provider refresh token
|
|
35
|
+
* @param config - Provider configuration
|
|
36
|
+
* @returns New provider tokens or error
|
|
37
|
+
*/
|
|
38
|
+
export declare function refreshProviderToken(refreshToken: string, config: ProviderRefreshConfig): Promise<RefreshResult>;
|
|
39
|
+
/**
|
|
40
|
+
* Check if a token is expired or will expire soon.
|
|
41
|
+
*
|
|
42
|
+
* @param expiresAt - Token expiry timestamp (ms)
|
|
43
|
+
* @param bufferMs - Buffer time before expiry to consider "near expiry"
|
|
44
|
+
* @returns true if token is expired or expiring within buffer
|
|
45
|
+
*/
|
|
46
|
+
export declare function isTokenExpiredOrExpiring(expiresAt: number | undefined, bufferMs?: number): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Proactively refresh token if near expiry.
|
|
49
|
+
*
|
|
50
|
+
* This should be called before tool execution to ensure fresh tokens.
|
|
51
|
+
* Updates the token store with new tokens if refresh succeeds.
|
|
52
|
+
*
|
|
53
|
+
* @param rsAccessToken - The RS access token to check
|
|
54
|
+
* @param tokenStore - Token storage
|
|
55
|
+
* @param providerConfig - Provider configuration for refresh
|
|
56
|
+
* @returns Refreshed provider access token, or original if refresh not needed/failed
|
|
57
|
+
*/
|
|
58
|
+
export declare function ensureFreshToken(rsAccessToken: string, tokenStore: TokenStore, providerConfig: ProviderRefreshConfig | undefined): Promise<{
|
|
59
|
+
accessToken: string;
|
|
60
|
+
wasRefreshed: boolean;
|
|
61
|
+
}>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type SsrfCheckResult = {
|
|
2
|
+
safe: true;
|
|
3
|
+
} | {
|
|
4
|
+
safe: false;
|
|
5
|
+
reason: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Validate a URL for SSRF safety before making outbound requests.
|
|
9
|
+
*
|
|
10
|
+
* Rules:
|
|
11
|
+
* - Must be HTTPS (HTTP blocked)
|
|
12
|
+
* - Must not target localhost or loopback
|
|
13
|
+
* - Must not target private IP ranges
|
|
14
|
+
* - Must not target internal domain patterns
|
|
15
|
+
* - Must have non-root pathname (for CIMD URLs)
|
|
16
|
+
*/
|
|
17
|
+
export declare function checkSsrfSafe(urlString: string, options?: {
|
|
18
|
+
requireNonRootPath?: boolean;
|
|
19
|
+
}): SsrfCheckResult;
|
|
20
|
+
/**
|
|
21
|
+
* Convenience function that returns boolean
|
|
22
|
+
*/
|
|
23
|
+
export declare function isSsrfSafe(urlString: string, options?: {
|
|
24
|
+
requireNonRootPath?: boolean;
|
|
25
|
+
}): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Throws if URL is not SSRF-safe
|
|
28
|
+
*/
|
|
29
|
+
export declare function assertSsrfSafe(urlString: string, options?: {
|
|
30
|
+
requireNonRootPath?: boolean;
|
|
31
|
+
}): void;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export type AuthorizeInput = {
|
|
2
|
+
clientId?: string;
|
|
3
|
+
codeChallenge: string;
|
|
4
|
+
codeChallengeMethod: string;
|
|
5
|
+
redirectUri: string;
|
|
6
|
+
requestedScope?: string;
|
|
7
|
+
state?: string;
|
|
8
|
+
sid?: string;
|
|
9
|
+
};
|
|
10
|
+
export type { CimdConfig, ClientMetadata } from "./cimd.js";
|
|
11
|
+
export type AuthorizeResult = {
|
|
12
|
+
redirectTo: string;
|
|
13
|
+
txnId: string;
|
|
14
|
+
};
|
|
15
|
+
export type CallbackInput = {
|
|
16
|
+
providerCode: string;
|
|
17
|
+
compositeState: string;
|
|
18
|
+
};
|
|
19
|
+
export type CallbackResult = {
|
|
20
|
+
redirectTo: string;
|
|
21
|
+
txnId: string;
|
|
22
|
+
providerTokens: {
|
|
23
|
+
access_token: string;
|
|
24
|
+
refresh_token?: string;
|
|
25
|
+
expires_at?: number;
|
|
26
|
+
scopes?: string[];
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export type TokenInput = {
|
|
30
|
+
grant: "authorization_code";
|
|
31
|
+
code: string;
|
|
32
|
+
codeVerifier: string;
|
|
33
|
+
} | {
|
|
34
|
+
grant: "refresh_token";
|
|
35
|
+
refreshToken: string;
|
|
36
|
+
};
|
|
37
|
+
export type TokenResult = {
|
|
38
|
+
access_token: string;
|
|
39
|
+
refresh_token: string;
|
|
40
|
+
token_type: "bearer";
|
|
41
|
+
expires_in: number;
|
|
42
|
+
scope: string;
|
|
43
|
+
};
|
|
44
|
+
export type RegisterInput = {
|
|
45
|
+
redirect_uris?: string[];
|
|
46
|
+
grant_types?: string[];
|
|
47
|
+
response_types?: string[];
|
|
48
|
+
client_name?: string;
|
|
49
|
+
};
|
|
50
|
+
export type RegisterResult = {
|
|
51
|
+
client_id: string;
|
|
52
|
+
client_id_issued_at: number;
|
|
53
|
+
client_secret_expires_at: number;
|
|
54
|
+
token_endpoint_auth_method: string;
|
|
55
|
+
redirect_uris: string[];
|
|
56
|
+
grant_types: string[];
|
|
57
|
+
response_types: string[];
|
|
58
|
+
registration_client_uri: string;
|
|
59
|
+
registration_access_token: string;
|
|
60
|
+
client_name?: string;
|
|
61
|
+
};
|
|
62
|
+
export type ProviderConfig = {
|
|
63
|
+
clientId?: string;
|
|
64
|
+
clientSecret?: string;
|
|
65
|
+
accountsUrl: string;
|
|
66
|
+
oauthScopes: string;
|
|
67
|
+
/** Extra query params for authorization URL (e.g., "access_type=offline&prompt=consent") */
|
|
68
|
+
extraAuthParams?: string;
|
|
69
|
+
/** Path to authorization endpoint (default: /authorize for most providers) */
|
|
70
|
+
authorizationEndpointPath?: string;
|
|
71
|
+
/** Path to token endpoint - varies by provider (Spotify: /api/token, Google: /token, GitHub: /login/oauth/access_token) */
|
|
72
|
+
tokenEndpointPath?: string;
|
|
73
|
+
};
|
|
74
|
+
export type OAuthConfig = {
|
|
75
|
+
redirectUri: string;
|
|
76
|
+
redirectAllowlist: string[];
|
|
77
|
+
redirectAllowAll: boolean;
|
|
78
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type PromptArgs = Record<string, unknown>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type HttpClientInput = string | URL | {
|
|
2
|
+
url?: string;
|
|
3
|
+
} | Request;
|
|
4
|
+
export type HttpClient = (input: HttpClientInput, init?: RequestInit) => Promise<Response>;
|
|
5
|
+
export interface HttpClientOptions {
|
|
6
|
+
baseHeaders?: Record<string, string>;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
retries?: number;
|
|
9
|
+
retryDelay?: number;
|
|
10
|
+
rateLimit?: {
|
|
11
|
+
rps: number;
|
|
12
|
+
burst: number;
|
|
13
|
+
};
|
|
14
|
+
concurrency?: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function createHttpClient(options?: HttpClientOptions): HttpClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./http-client.js";
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export type ProviderTokens = {
|
|
2
|
+
access_token: string;
|
|
3
|
+
refresh_token?: string;
|
|
4
|
+
expires_at?: number;
|
|
5
|
+
scopes?: string[];
|
|
6
|
+
};
|
|
7
|
+
export type RsRecord = {
|
|
8
|
+
rs_access_token: string;
|
|
9
|
+
rs_refresh_token: string;
|
|
10
|
+
provider: ProviderTokens;
|
|
11
|
+
created_at: number;
|
|
12
|
+
};
|
|
13
|
+
export type Transaction = {
|
|
14
|
+
codeChallenge: string;
|
|
15
|
+
state?: string;
|
|
16
|
+
scope?: string;
|
|
17
|
+
createdAt: number;
|
|
18
|
+
sid?: string;
|
|
19
|
+
provider?: ProviderTokens;
|
|
20
|
+
/** Client's redirect_uri — stored at authorize time so callback can redirect without allowlist */
|
|
21
|
+
clientRedirectUri?: string;
|
|
22
|
+
};
|
|
23
|
+
export type SessionRecord = {
|
|
24
|
+
/** API key that owns this session (for multi-tenant support) */
|
|
25
|
+
apiKey?: string;
|
|
26
|
+
rs_access_token?: string;
|
|
27
|
+
rs_refresh_token?: string;
|
|
28
|
+
provider?: ProviderTokens | null;
|
|
29
|
+
created_at: number;
|
|
30
|
+
last_accessed: number;
|
|
31
|
+
/** Whether MCP initialize handshake completed */
|
|
32
|
+
initialized?: boolean;
|
|
33
|
+
/** Negotiated MCP protocol version */
|
|
34
|
+
protocolVersion?: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Token storage interface - all operations are async to support both
|
|
38
|
+
* sync (Node Map + File) and async (Cloudflare KV) backends
|
|
39
|
+
*/
|
|
40
|
+
export interface TokenStore {
|
|
41
|
+
storeRsMapping(rsAccess: string, provider: ProviderTokens, rsRefresh?: string): Promise<RsRecord>;
|
|
42
|
+
getByRsAccess(rsAccess: string): Promise<RsRecord | null>;
|
|
43
|
+
getByRsRefresh(rsRefresh: string): Promise<RsRecord | null>;
|
|
44
|
+
updateByRsRefresh(rsRefresh: string, provider: ProviderTokens, maybeNewRsAccess?: string): Promise<RsRecord | null>;
|
|
45
|
+
saveTransaction(txnId: string, txn: Transaction, ttlSeconds?: number): Promise<void>;
|
|
46
|
+
getTransaction(txnId: string): Promise<Transaction | null>;
|
|
47
|
+
deleteTransaction(txnId: string): Promise<void>;
|
|
48
|
+
saveCode(code: string, txnId: string, ttlSeconds?: number): Promise<void>;
|
|
49
|
+
getTxnIdByCode(code: string): Promise<string | null>;
|
|
50
|
+
deleteCode(code: string): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
/** Maximum sessions allowed per API key */
|
|
53
|
+
export declare const MAX_SESSIONS_PER_API_KEY = 5;
|
|
54
|
+
/**
|
|
55
|
+
* Session storage interface for multi-tenant MCP servers.
|
|
56
|
+
* Supports tracking sessions per API key with limits and LRU eviction.
|
|
57
|
+
*/
|
|
58
|
+
export interface SessionStore {
|
|
59
|
+
/**
|
|
60
|
+
* Create a new session for an API key.
|
|
61
|
+
* Automatically enforces MAX_SESSIONS_PER_API_KEY limit with LRU eviction.
|
|
62
|
+
*/
|
|
63
|
+
create(sessionId: string, apiKey: string): Promise<SessionRecord>;
|
|
64
|
+
/**
|
|
65
|
+
* Get a session by ID. Returns null if not found or expired.
|
|
66
|
+
* Updates last_accessed timestamp on access.
|
|
67
|
+
*/
|
|
68
|
+
get(sessionId: string): Promise<SessionRecord | null>;
|
|
69
|
+
/**
|
|
70
|
+
* Update session data (e.g., mark as initialized, store protocol version).
|
|
71
|
+
*/
|
|
72
|
+
update(sessionId: string, data: Partial<SessionRecord>): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Delete a session.
|
|
75
|
+
*/
|
|
76
|
+
delete(sessionId: string): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Get all sessions for an API key.
|
|
79
|
+
*/
|
|
80
|
+
getByApiKey(apiKey: string): Promise<SessionRecord[]>;
|
|
81
|
+
/**
|
|
82
|
+
* Count active sessions for an API key.
|
|
83
|
+
*/
|
|
84
|
+
countByApiKey(apiKey: string): Promise<number>;
|
|
85
|
+
/**
|
|
86
|
+
* Delete the oldest session for an API key (LRU eviction).
|
|
87
|
+
*/
|
|
88
|
+
deleteOldestByApiKey(apiKey: string): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Ensure a session exists (legacy compat). Creates minimal session if missing.
|
|
91
|
+
* @deprecated Use create() for new code
|
|
92
|
+
*/
|
|
93
|
+
ensure(sessionId: string): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Put a session record directly (legacy compat).
|
|
96
|
+
* @deprecated Use create() or update() for new code
|
|
97
|
+
*/
|
|
98
|
+
put(sessionId: string, value: SessionRecord): Promise<void>;
|
|
99
|
+
}
|