integrate-sdk 0.3.6 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +0 -102
- package/dist/src/adapters/nextjs-callback.d.ts +6 -2
- package/dist/src/adapters/nextjs-callback.d.ts.map +1 -1
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/adapters/auto-routes.ts +217 -0
- package/src/adapters/base-handler.ts +212 -0
- package/src/adapters/nextjs-callback.tsx +160 -0
- package/src/adapters/nextjs.ts +318 -0
- package/src/adapters/tanstack-start.ts +264 -0
- package/src/client.ts +952 -0
- package/src/config/types.ts +180 -0
- package/src/errors.ts +207 -0
- package/src/index.ts +110 -0
- package/src/integrations/vercel-ai.ts +104 -0
- package/src/oauth/manager.ts +307 -0
- package/src/oauth/pkce.ts +127 -0
- package/src/oauth/types.ts +101 -0
- package/src/oauth/window-manager.ts +322 -0
- package/src/plugins/generic.ts +119 -0
- package/src/plugins/github-client.ts +345 -0
- package/src/plugins/github.ts +122 -0
- package/src/plugins/gmail-client.ts +114 -0
- package/src/plugins/gmail.ts +108 -0
- package/src/plugins/server-client.ts +20 -0
- package/src/plugins/types.ts +89 -0
- package/src/protocol/jsonrpc.ts +88 -0
- package/src/protocol/messages.ts +145 -0
- package/src/server.ts +117 -0
- package/src/transport/http-session.ts +322 -0
- package/src/transport/http-stream.ts +331 -0
- package/src/utils/naming.ts +52 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Types
|
|
3
|
+
* Type-safe configuration with inference
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { MCPPlugin } from "../plugins/types.js";
|
|
7
|
+
import type { AuthenticationError } from "../errors.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Re-authentication context provided to the callback
|
|
11
|
+
*/
|
|
12
|
+
export interface ReauthContext {
|
|
13
|
+
/** The plugin/provider that needs re-authentication */
|
|
14
|
+
provider: string;
|
|
15
|
+
/** The error that triggered re-authentication */
|
|
16
|
+
error: AuthenticationError;
|
|
17
|
+
/** The tool name that was being called (if applicable) */
|
|
18
|
+
toolName?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Re-authentication handler function
|
|
23
|
+
* Called when authentication fails and user needs to re-authenticate
|
|
24
|
+
* Should return true if re-authentication was successful, false otherwise
|
|
25
|
+
*/
|
|
26
|
+
export type ReauthHandler = (context: ReauthContext) => Promise<boolean> | boolean;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Main client configuration
|
|
30
|
+
*/
|
|
31
|
+
export interface MCPClientConfig<TPlugins extends readonly MCPPlugin[]> {
|
|
32
|
+
/** Array of plugins to enable */
|
|
33
|
+
plugins: TPlugins;
|
|
34
|
+
|
|
35
|
+
/** Optional HTTP headers to include in requests */
|
|
36
|
+
headers?: Record<string, string>;
|
|
37
|
+
|
|
38
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
39
|
+
timeout?: number;
|
|
40
|
+
|
|
41
|
+
/** Client information */
|
|
42
|
+
clientInfo?: {
|
|
43
|
+
name: string;
|
|
44
|
+
version: string;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Handler called when authentication fails and re-authentication is needed
|
|
49
|
+
* This is typically called when OAuth tokens expire or become invalid
|
|
50
|
+
*
|
|
51
|
+
* @param context - Information about the authentication failure
|
|
52
|
+
* @returns Promise<boolean> - true if re-authentication was successful, false otherwise
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const client = createMCPClient({
|
|
57
|
+
* plugins: [githubPlugin(...)],
|
|
58
|
+
* onReauthRequired: async (context) => {
|
|
59
|
+
* console.log(`Re-auth needed for ${context.provider}`);
|
|
60
|
+
* // Trigger your OAuth flow here
|
|
61
|
+
* // Return true if successful, false otherwise
|
|
62
|
+
* return await triggerOAuthFlow(context.provider);
|
|
63
|
+
* }
|
|
64
|
+
* });
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
onReauthRequired?: ReauthHandler;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Maximum number of automatic retry attempts when authentication fails
|
|
71
|
+
* Default: 1 (one retry after re-authentication)
|
|
72
|
+
* Set to 0 to disable automatic retries
|
|
73
|
+
*/
|
|
74
|
+
maxReauthRetries?: number;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Connection behavior
|
|
78
|
+
*
|
|
79
|
+
* - 'lazy' (default): Automatically connects on first method call
|
|
80
|
+
* - 'eager': Connects immediately when createMCPClient is called
|
|
81
|
+
* - 'manual': Requires manual connect() call (original behavior)
|
|
82
|
+
*
|
|
83
|
+
* @default 'lazy'
|
|
84
|
+
*/
|
|
85
|
+
connectionMode?: 'lazy' | 'eager' | 'manual';
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Whether to use singleton pattern and reuse client instances
|
|
89
|
+
*
|
|
90
|
+
* - true (default): Reuses client with same configuration
|
|
91
|
+
* - false: Always creates a new instance
|
|
92
|
+
*
|
|
93
|
+
* @default true
|
|
94
|
+
*/
|
|
95
|
+
singleton?: boolean;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Automatically cleanup (disconnect) on process exit
|
|
99
|
+
*
|
|
100
|
+
* @default true
|
|
101
|
+
*/
|
|
102
|
+
autoCleanup?: boolean;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* OAuth flow configuration
|
|
106
|
+
* Controls how OAuth authorization is handled (popup vs redirect)
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const client = createMCPClient({
|
|
111
|
+
* plugins: [githubPlugin({ ... })],
|
|
112
|
+
* oauthFlow: {
|
|
113
|
+
* mode: 'popup',
|
|
114
|
+
* popupOptions: { width: 600, height: 700 }
|
|
115
|
+
* }
|
|
116
|
+
* });
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
oauthFlow?: {
|
|
120
|
+
/** How to display OAuth authorization (default: 'redirect') */
|
|
121
|
+
mode?: 'popup' | 'redirect';
|
|
122
|
+
/** Popup window dimensions (only for popup mode) */
|
|
123
|
+
popupOptions?: {
|
|
124
|
+
width?: number;
|
|
125
|
+
height?: number;
|
|
126
|
+
};
|
|
127
|
+
/** Custom callback handler for receiving auth code */
|
|
128
|
+
onAuthCallback?: (provider: string, code: string, state: string) => Promise<void>;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Session token for authenticated requests
|
|
133
|
+
* Set automatically after OAuth flow completes
|
|
134
|
+
* Can be provided manually if you manage tokens externally
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const client = createMCPClient({
|
|
139
|
+
* plugins: [githubPlugin({ ... })],
|
|
140
|
+
* sessionToken: 'existing-session-token'
|
|
141
|
+
* });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
sessionToken?: string;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Base URL for OAuth API routes
|
|
148
|
+
* These routes should be mounted in your application to handle OAuth securely
|
|
149
|
+
*
|
|
150
|
+
* The SDK will call:
|
|
151
|
+
* - POST {oauthApiBase}/authorize - Get authorization URL
|
|
152
|
+
* - POST {oauthApiBase}/callback - Exchange code for token
|
|
153
|
+
* - GET {oauthApiBase}/status - Check authorization status
|
|
154
|
+
*
|
|
155
|
+
* @default '/api/integrate/oauth'
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* const client = createMCPClient({
|
|
160
|
+
* plugins: [githubPlugin({ ... })],
|
|
161
|
+
* oauthApiBase: '/api/integrate/oauth'
|
|
162
|
+
* });
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
oauthApiBase?: string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Helper type to infer enabled tools from plugins
|
|
170
|
+
*/
|
|
171
|
+
export type InferEnabledTools<TPlugins extends readonly MCPPlugin[]> =
|
|
172
|
+
TPlugins[number]["tools"][number];
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Helper type to create a tools object type from plugin array
|
|
176
|
+
*/
|
|
177
|
+
export type InferToolsObject<TPlugins extends readonly MCPPlugin[]> = {
|
|
178
|
+
[K in TPlugins[number] as K["id"]]: K["tools"];
|
|
179
|
+
};
|
|
180
|
+
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error types for the Integrate SDK
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Base error class for all SDK errors
|
|
7
|
+
*/
|
|
8
|
+
export class IntegrateSDKError extends Error {
|
|
9
|
+
constructor(message: string) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "IntegrateSDKError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Error thrown when authentication fails or tokens are invalid
|
|
17
|
+
*/
|
|
18
|
+
export class AuthenticationError extends IntegrateSDKError {
|
|
19
|
+
public readonly statusCode?: number;
|
|
20
|
+
public readonly provider?: string;
|
|
21
|
+
|
|
22
|
+
constructor(message: string, statusCode?: number, provider?: string) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = "AuthenticationError";
|
|
25
|
+
this.statusCode = statusCode;
|
|
26
|
+
this.provider = provider;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Error thrown when access is forbidden (insufficient permissions)
|
|
32
|
+
*/
|
|
33
|
+
export class AuthorizationError extends IntegrateSDKError {
|
|
34
|
+
public readonly statusCode?: number;
|
|
35
|
+
public readonly requiredScopes?: string[];
|
|
36
|
+
|
|
37
|
+
constructor(message: string, statusCode?: number, requiredScopes?: string[]) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.name = "AuthorizationError";
|
|
40
|
+
this.statusCode = statusCode;
|
|
41
|
+
this.requiredScopes = requiredScopes;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Error thrown when OAuth tokens have expired and need to be refreshed
|
|
47
|
+
*/
|
|
48
|
+
export class TokenExpiredError extends AuthenticationError {
|
|
49
|
+
constructor(message: string, provider?: string) {
|
|
50
|
+
super(message, 401, provider);
|
|
51
|
+
this.name = "TokenExpiredError";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Error thrown when a connection to the server fails
|
|
57
|
+
*/
|
|
58
|
+
export class ConnectionError extends IntegrateSDKError {
|
|
59
|
+
public readonly statusCode?: number;
|
|
60
|
+
|
|
61
|
+
constructor(message: string, statusCode?: number) {
|
|
62
|
+
super(message);
|
|
63
|
+
this.name = "ConnectionError";
|
|
64
|
+
this.statusCode = statusCode;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Error thrown when a tool call fails
|
|
70
|
+
*/
|
|
71
|
+
export class ToolCallError extends IntegrateSDKError {
|
|
72
|
+
public readonly toolName: string;
|
|
73
|
+
public readonly originalError?: unknown;
|
|
74
|
+
|
|
75
|
+
constructor(message: string, toolName: string, originalError?: unknown) {
|
|
76
|
+
super(message);
|
|
77
|
+
this.name = "ToolCallError";
|
|
78
|
+
this.toolName = toolName;
|
|
79
|
+
this.originalError = originalError;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Helper function to determine if an error is an authentication error
|
|
85
|
+
*/
|
|
86
|
+
export function isAuthError(error: unknown): error is AuthenticationError {
|
|
87
|
+
return error instanceof AuthenticationError;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Helper function to determine if an error is a token expired error
|
|
92
|
+
*/
|
|
93
|
+
export function isTokenExpiredError(error: unknown): error is TokenExpiredError {
|
|
94
|
+
return error instanceof TokenExpiredError;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Helper function to determine if an error is an authorization error
|
|
99
|
+
*/
|
|
100
|
+
export function isAuthorizationError(error: unknown): error is AuthorizationError {
|
|
101
|
+
return error instanceof AuthorizationError;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Helper function to parse error responses from the MCP server
|
|
106
|
+
* and convert them to appropriate error types
|
|
107
|
+
*/
|
|
108
|
+
export function parseServerError(
|
|
109
|
+
error: any,
|
|
110
|
+
context?: { toolName?: string; provider?: string }
|
|
111
|
+
): IntegrateSDKError {
|
|
112
|
+
// Check if the error has an attached JSON-RPC error (from transport layer)
|
|
113
|
+
if (error && typeof error === "object" && "jsonrpcError" in error) {
|
|
114
|
+
const jsonrpcError = error.jsonrpcError;
|
|
115
|
+
if (jsonrpcError && typeof jsonrpcError === "object") {
|
|
116
|
+
return parseServerError(jsonrpcError, context);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Check for JSON-RPC error format
|
|
121
|
+
if (error && typeof error === "object" && "code" in error && "message" in error) {
|
|
122
|
+
const code = error.code;
|
|
123
|
+
const message = error.message || "Unknown error";
|
|
124
|
+
|
|
125
|
+
// Standard JSON-RPC error codes
|
|
126
|
+
if (code === -32600) {
|
|
127
|
+
return new IntegrateSDKError(`Invalid request: ${message}`);
|
|
128
|
+
}
|
|
129
|
+
if (code === -32601) {
|
|
130
|
+
return new IntegrateSDKError(`Method not found: ${message}`);
|
|
131
|
+
}
|
|
132
|
+
if (code === -32602) {
|
|
133
|
+
return new IntegrateSDKError(`Invalid params: ${message}`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Custom authentication error codes
|
|
137
|
+
if (code === 401 || code === -32001) {
|
|
138
|
+
// Check if it's a token expiry
|
|
139
|
+
if (
|
|
140
|
+
message.toLowerCase().includes("expired") ||
|
|
141
|
+
message.toLowerCase().includes("token")
|
|
142
|
+
) {
|
|
143
|
+
return new TokenExpiredError(message, context?.provider);
|
|
144
|
+
}
|
|
145
|
+
return new AuthenticationError(message, 401, context?.provider);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Authorization errors
|
|
149
|
+
if (code === 403 || code === -32002) {
|
|
150
|
+
return new AuthorizationError(message, 403);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Tool-specific errors
|
|
154
|
+
if (context?.toolName) {
|
|
155
|
+
return new ToolCallError(message, context.toolName, error);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return new IntegrateSDKError(message);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Handle regular Error objects
|
|
162
|
+
if (error instanceof Error) {
|
|
163
|
+
const message = error.message;
|
|
164
|
+
|
|
165
|
+
// Check for HTTP status code attached to error
|
|
166
|
+
const statusCode = (error as any).statusCode;
|
|
167
|
+
if (statusCode === 401) {
|
|
168
|
+
if (message.toLowerCase().includes("expired") || message.toLowerCase().includes("token")) {
|
|
169
|
+
return new TokenExpiredError(message, context?.provider);
|
|
170
|
+
}
|
|
171
|
+
return new AuthenticationError(message, 401, context?.provider);
|
|
172
|
+
}
|
|
173
|
+
if (statusCode === 403) {
|
|
174
|
+
return new AuthorizationError(message, 403);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Check for common auth error patterns in message
|
|
178
|
+
if (
|
|
179
|
+
message.includes("401") ||
|
|
180
|
+
message.includes("Unauthorized") ||
|
|
181
|
+
message.includes("unauthenticated")
|
|
182
|
+
) {
|
|
183
|
+
if (message.toLowerCase().includes("expired") || message.toLowerCase().includes("token")) {
|
|
184
|
+
return new TokenExpiredError(message, context?.provider);
|
|
185
|
+
}
|
|
186
|
+
return new AuthenticationError(message, 401, context?.provider);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (
|
|
190
|
+
message.includes("403") ||
|
|
191
|
+
message.includes("Forbidden") ||
|
|
192
|
+
message.includes("unauthorized")
|
|
193
|
+
) {
|
|
194
|
+
return new AuthorizationError(message, 403);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (context?.toolName) {
|
|
198
|
+
return new ToolCallError(message, context.toolName, error);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return new IntegrateSDKError(message);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Fallback
|
|
205
|
+
return new IntegrateSDKError(String(error));
|
|
206
|
+
}
|
|
207
|
+
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integrate SDK
|
|
3
|
+
* Type-safe TypeScript SDK for MCP Client
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Core client
|
|
7
|
+
export { MCPClient, createMCPClient, clearClientCache } from "./client.js";
|
|
8
|
+
export type { ToolInvocationOptions } from "./client.js";
|
|
9
|
+
|
|
10
|
+
// OAuth utilities
|
|
11
|
+
export { OAuthManager } from "./oauth/manager.js";
|
|
12
|
+
export { OAuthWindowManager, sendCallbackToOpener } from "./oauth/window-manager.js";
|
|
13
|
+
export { generateCodeVerifier, generateCodeChallenge, generateState } from "./oauth/pkce.js";
|
|
14
|
+
export type {
|
|
15
|
+
OAuthFlowConfig,
|
|
16
|
+
PopupOptions,
|
|
17
|
+
AuthStatus,
|
|
18
|
+
PendingAuth,
|
|
19
|
+
AuthorizationUrlResponse,
|
|
20
|
+
OAuthCallbackResponse,
|
|
21
|
+
OAuthCallbackParams,
|
|
22
|
+
OAuthCallbackHandlerConfig,
|
|
23
|
+
} from "./oauth/types.js";
|
|
24
|
+
|
|
25
|
+
// OAuth route adapters
|
|
26
|
+
export { OAuthHandler } from "./adapters/base-handler.js";
|
|
27
|
+
export type {
|
|
28
|
+
OAuthHandlerConfig,
|
|
29
|
+
AuthorizeRequest,
|
|
30
|
+
AuthorizeResponse,
|
|
31
|
+
CallbackRequest,
|
|
32
|
+
CallbackResponse,
|
|
33
|
+
StatusResponse,
|
|
34
|
+
} from "./adapters/base-handler.js";
|
|
35
|
+
export { createNextOAuthHandler } from "./adapters/nextjs.js";
|
|
36
|
+
export { createTanStackOAuthHandler } from "./adapters/tanstack-start.js";
|
|
37
|
+
|
|
38
|
+
// Configuration
|
|
39
|
+
export type { MCPClientConfig, ReauthContext, ReauthHandler } from "./config/types.js";
|
|
40
|
+
|
|
41
|
+
// Errors
|
|
42
|
+
export {
|
|
43
|
+
IntegrateSDKError,
|
|
44
|
+
AuthenticationError,
|
|
45
|
+
AuthorizationError,
|
|
46
|
+
TokenExpiredError,
|
|
47
|
+
ConnectionError,
|
|
48
|
+
ToolCallError,
|
|
49
|
+
isAuthError,
|
|
50
|
+
isTokenExpiredError,
|
|
51
|
+
isAuthorizationError,
|
|
52
|
+
parseServerError,
|
|
53
|
+
} from "./errors.js";
|
|
54
|
+
|
|
55
|
+
// Plugin system
|
|
56
|
+
export type {
|
|
57
|
+
MCPPlugin,
|
|
58
|
+
OAuthConfig,
|
|
59
|
+
ExtractPluginIds,
|
|
60
|
+
ExtractPluginTools,
|
|
61
|
+
} from "./plugins/types.js";
|
|
62
|
+
|
|
63
|
+
// Built-in plugins
|
|
64
|
+
export { githubPlugin } from "./plugins/github.js";
|
|
65
|
+
export type { GitHubPluginConfig, GitHubTools, GitHubPluginClient } from "./plugins/github.js";
|
|
66
|
+
|
|
67
|
+
export { gmailPlugin } from "./plugins/gmail.js";
|
|
68
|
+
export type { GmailPluginConfig, GmailTools, GmailPluginClient } from "./plugins/gmail.js";
|
|
69
|
+
|
|
70
|
+
// Server client
|
|
71
|
+
export type { ServerPluginClient } from "./plugins/server-client.js";
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
genericOAuthPlugin,
|
|
75
|
+
createSimplePlugin,
|
|
76
|
+
} from "./plugins/generic.js";
|
|
77
|
+
export type { GenericOAuthPluginConfig } from "./plugins/generic.js";
|
|
78
|
+
|
|
79
|
+
// Integrations
|
|
80
|
+
export {
|
|
81
|
+
convertMCPToolToVercelAI,
|
|
82
|
+
convertMCPToolsToVercelAI,
|
|
83
|
+
getVercelAITools,
|
|
84
|
+
} from "./integrations/vercel-ai.js";
|
|
85
|
+
export type { VercelAITool } from "./integrations/vercel-ai.js";
|
|
86
|
+
|
|
87
|
+
// Protocol types
|
|
88
|
+
export type {
|
|
89
|
+
JSONRPCRequest,
|
|
90
|
+
JSONRPCResponse,
|
|
91
|
+
JSONRPCSuccessResponse,
|
|
92
|
+
JSONRPCErrorResponse,
|
|
93
|
+
JSONRPCNotification,
|
|
94
|
+
MCPTool,
|
|
95
|
+
MCPToolsListResponse,
|
|
96
|
+
MCPToolCallParams,
|
|
97
|
+
MCPToolCallResponse,
|
|
98
|
+
MCPInitializeParams,
|
|
99
|
+
MCPInitializeResponse,
|
|
100
|
+
} from "./protocol/messages.js";
|
|
101
|
+
|
|
102
|
+
export { MCPMethod } from "./protocol/messages.js";
|
|
103
|
+
|
|
104
|
+
// Transport
|
|
105
|
+
export { HttpSessionTransport } from "./transport/http-session.js";
|
|
106
|
+
export type {
|
|
107
|
+
MessageHandler,
|
|
108
|
+
HttpSessionTransportOptions,
|
|
109
|
+
} from "./transport/http-session.js";
|
|
110
|
+
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vercel AI SDK Integration
|
|
3
|
+
*
|
|
4
|
+
* Helper functions to convert MCP tools to Vercel AI SDK format
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { MCPClient } from "../client.js";
|
|
8
|
+
import type { MCPTool } from "../protocol/messages.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Tool definition for Vercel AI SDK
|
|
12
|
+
*/
|
|
13
|
+
export interface VercelAITool {
|
|
14
|
+
description: string;
|
|
15
|
+
parameters: Record<string, unknown>;
|
|
16
|
+
execute: (args: Record<string, unknown>) => Promise<unknown>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Convert MCP JSON Schema to Vercel AI SDK parameters format
|
|
21
|
+
*
|
|
22
|
+
* Note: Vercel AI SDK typically uses Zod, but we return plain JSON Schema
|
|
23
|
+
* which is compatible with the AI SDK's schema parameter
|
|
24
|
+
*/
|
|
25
|
+
function convertMCPSchemaToParameters(inputSchema: Record<string, unknown>): Record<string, unknown> {
|
|
26
|
+
// MCP tools already use JSON Schema format
|
|
27
|
+
// Vercel AI SDK accepts JSON Schema or Zod schemas
|
|
28
|
+
return inputSchema;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Convert a single MCP tool to Vercel AI SDK format
|
|
33
|
+
*
|
|
34
|
+
* @param mcpTool - The MCP tool definition
|
|
35
|
+
* @param client - The MCP client instance (used for executing the tool)
|
|
36
|
+
* @returns Vercel AI SDK compatible tool definition
|
|
37
|
+
*/
|
|
38
|
+
export function convertMCPToolToVercelAI(
|
|
39
|
+
mcpTool: MCPTool,
|
|
40
|
+
client: MCPClient
|
|
41
|
+
): VercelAITool {
|
|
42
|
+
return {
|
|
43
|
+
description: mcpTool.description || `Execute ${mcpTool.name}`,
|
|
44
|
+
parameters: convertMCPSchemaToParameters(mcpTool.inputSchema),
|
|
45
|
+
execute: async (args: Record<string, unknown>) => {
|
|
46
|
+
// Use internal method to call tools by name for integration purposes
|
|
47
|
+
const result = await client._callToolByName(mcpTool.name, args);
|
|
48
|
+
return result;
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Convert all enabled MCP tools to Vercel AI SDK format
|
|
55
|
+
*
|
|
56
|
+
* @param client - The MCP client instance (must be connected)
|
|
57
|
+
* @returns Object mapping tool names to Vercel AI SDK tool definitions
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* import { createMCPClient, githubPlugin } from 'integrate-sdk';
|
|
62
|
+
* import { convertMCPToolsToVercelAI } from 'integrate-sdk/vercel-ai';
|
|
63
|
+
* import { generateText } from 'ai';
|
|
64
|
+
*
|
|
65
|
+
* const mcpClient = createMCPClient({
|
|
66
|
+
* plugins: [githubPlugin({ clientId: '...', clientSecret: '...' })],
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* await mcpClient.connect();
|
|
70
|
+
*
|
|
71
|
+
* const tools = convertMCPToolsToVercelAI(mcpClient);
|
|
72
|
+
*
|
|
73
|
+
* const result = await generateText({
|
|
74
|
+
* model: openai('gpt-5'),
|
|
75
|
+
* prompt: 'Create a GitHub issue in my repo',
|
|
76
|
+
* tools,
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export function convertMCPToolsToVercelAI(
|
|
81
|
+
client: MCPClient
|
|
82
|
+
): Record<string, VercelAITool> {
|
|
83
|
+
const mcpTools = client.getEnabledTools();
|
|
84
|
+
const vercelTools: Record<string, VercelAITool> = {};
|
|
85
|
+
|
|
86
|
+
for (const mcpTool of mcpTools) {
|
|
87
|
+
vercelTools[mcpTool.name] = convertMCPToolToVercelAI(mcpTool, client);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return vercelTools;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get tools in a format compatible with Vercel AI SDK's tools parameter
|
|
95
|
+
*
|
|
96
|
+
* This is an alternative that returns the tools in the exact format expected by ai.generateText()
|
|
97
|
+
*
|
|
98
|
+
* @param client - The MCP client instance (must be connected)
|
|
99
|
+
* @returns Tools object ready to pass to generateText({ tools: ... })
|
|
100
|
+
*/
|
|
101
|
+
export function getVercelAITools(client: MCPClient) {
|
|
102
|
+
return convertMCPToolsToVercelAI(client);
|
|
103
|
+
}
|
|
104
|
+
|