integrate-sdk 0.1.5 → 0.1.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/LICENSE +1 -1
- package/README.md +58 -603
- package/dist/client.d.ts +29 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/config/types.d.ts +45 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/errors.d.ts +67 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +258 -5
- package/dist/integrations/vercel-ai.d.ts +1 -1
- package/dist/transport/http-session.d.ts.map +1 -1
- package/package.json +2 -3
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -6,35 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
A type-safe TypeScript SDK for connecting to the Integrate MCP (Model Context Protocol) server. Access GitHub, Gmail, Notion, and other integrations through a simple, plugin-based API.
|
|
8
8
|
|
|
9
|
-
**Server:** `https://mcp.integrate.dev/api/v1/mcp`
|
|
10
|
-
|
|
11
|
-
## Table of Contents
|
|
12
|
-
|
|
13
|
-
- [What is this SDK?](#what-is-this-sdk)
|
|
14
|
-
- [Features](#features)
|
|
15
|
-
- [Installation](#installation)
|
|
16
|
-
- [Quick Start](#quick-start)
|
|
17
|
-
- [Built-in Plugins](#built-in-plugins)
|
|
18
|
-
- [GitHub Plugin](#github-plugin)
|
|
19
|
-
- [Gmail Plugin](#gmail-plugin)
|
|
20
|
-
- [Creating Custom Plugins](#creating-custom-plugins)
|
|
21
|
-
- [Integration with Vercel AI SDK](#integration-with-vercel-ai-sdk)
|
|
22
|
-
- [Advanced Usage](#advanced-usage)
|
|
23
|
-
- [API Reference](#api-reference)
|
|
24
|
-
- [Architecture](#architecture)
|
|
25
|
-
- [How It Works](#how-it-works)
|
|
26
|
-
|
|
27
|
-
## What is this SDK?
|
|
28
|
-
|
|
29
|
-
This SDK is a **client library** that connects to the Integrate MCP server to access various third-party integrations.
|
|
30
|
-
|
|
31
|
-
**Key concepts:**
|
|
32
|
-
1. **Connect to the Integrate MCP server** - The SDK connects to `https://mcp.integrate.dev/api/v1/mcp`
|
|
33
|
-
2. **Configure OAuth credentials** - You provide your own OAuth app credentials for each integration (GitHub, Gmail, etc.)
|
|
34
|
-
3. **Call tools** - Execute actions like creating GitHub issues, sending emails, searching Notion pages
|
|
35
|
-
4. **OAuth flow happens server-side** - The SDK sends your OAuth config to the server, which handles the actual authentication flow
|
|
36
|
-
|
|
37
|
-
**Important:** You need to create your own OAuth apps (e.g., GitHub OAuth app, Google OAuth app) and provide the credentials to the SDK. The SDK does not provide OAuth credentials.
|
|
9
|
+
**📚 [Full Documentation](https://integrate.dev)** | **Server:** `https://mcp.integrate.dev/api/v1/mcp`
|
|
38
10
|
|
|
39
11
|
## Features
|
|
40
12
|
|
|
@@ -56,7 +28,7 @@ bun add integrate-sdk
|
|
|
56
28
|
## Quick Start
|
|
57
29
|
|
|
58
30
|
```typescript
|
|
59
|
-
import { createMCPClient, githubPlugin
|
|
31
|
+
import { createMCPClient, githubPlugin } from "integrate-sdk";
|
|
60
32
|
|
|
61
33
|
// Create a client with plugins
|
|
62
34
|
const client = createMCPClient({
|
|
@@ -64,11 +36,7 @@ const client = createMCPClient({
|
|
|
64
36
|
githubPlugin({
|
|
65
37
|
clientId: process.env.GITHUB_CLIENT_ID!,
|
|
66
38
|
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
|
|
67
|
-
scopes: [
|
|
68
|
-
}),
|
|
69
|
-
gmailPlugin({
|
|
70
|
-
clientId: process.env.GMAIL_CLIENT_ID!,
|
|
71
|
-
clientSecret: process.env.GMAIL_CLIENT_SECRET!,
|
|
39
|
+
scopes: ["repo", "user"],
|
|
72
40
|
}),
|
|
73
41
|
],
|
|
74
42
|
});
|
|
@@ -76,636 +44,123 @@ const client = createMCPClient({
|
|
|
76
44
|
// Connect to the server
|
|
77
45
|
await client.connect();
|
|
78
46
|
|
|
79
|
-
// Call
|
|
80
|
-
const result = await client.callTool(
|
|
81
|
-
repo:
|
|
82
|
-
title:
|
|
83
|
-
body:
|
|
47
|
+
// Call a tool
|
|
48
|
+
const result = await client.callTool("github_create_issue", {
|
|
49
|
+
repo: "owner/repo",
|
|
50
|
+
title: "Bug report",
|
|
51
|
+
body: "Description of the bug",
|
|
84
52
|
});
|
|
85
53
|
|
|
86
|
-
console.log(
|
|
54
|
+
console.log("Issue created:", result);
|
|
87
55
|
|
|
88
56
|
// Disconnect when done
|
|
89
57
|
await client.disconnect();
|
|
90
58
|
```
|
|
91
59
|
|
|
60
|
+
**Need help?** Check out the [complete documentation](https://integrate.dev) for detailed guides, examples, and API reference.
|
|
61
|
+
|
|
92
62
|
## Built-in Plugins
|
|
93
63
|
|
|
94
64
|
### GitHub Plugin
|
|
95
65
|
|
|
96
|
-
|
|
97
|
-
import { createMCPClient, githubPlugin } from 'integrate-sdk';
|
|
66
|
+
Access GitHub repositories, issues, pull requests, and more.
|
|
98
67
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
scopes: ['repo', 'user', 'read:org'], // Optional, defaults to ['repo', 'user']
|
|
105
|
-
redirectUri: 'http://localhost:3000/callback', // Optional
|
|
106
|
-
}),
|
|
107
|
-
],
|
|
68
|
+
```typescript
|
|
69
|
+
githubPlugin({
|
|
70
|
+
clientId: process.env.GITHUB_CLIENT_ID!,
|
|
71
|
+
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
|
|
72
|
+
scopes: ["repo", "user"],
|
|
108
73
|
});
|
|
109
74
|
```
|
|
110
75
|
|
|
111
|
-
|
|
112
|
-
- `github_create_issue`
|
|
113
|
-
- `github_list_issues`
|
|
114
|
-
- `github_get_issue`
|
|
115
|
-
- `github_update_issue`
|
|
116
|
-
- `github_close_issue`
|
|
117
|
-
- `github_create_pull_request`
|
|
118
|
-
- `github_list_pull_requests`
|
|
119
|
-
- `github_get_pull_request`
|
|
120
|
-
- `github_merge_pull_request`
|
|
121
|
-
- `github_list_repos`
|
|
122
|
-
- `github_list_own_repos`
|
|
123
|
-
- `github_get_repo`
|
|
124
|
-
- `github_create_repo`
|
|
125
|
-
- And more...
|
|
76
|
+
[→ View GitHub plugin documentation](https://integrate.dev/docs/plugins/github)
|
|
126
77
|
|
|
127
78
|
### Gmail Plugin
|
|
128
79
|
|
|
129
|
-
|
|
130
|
-
import { createMCPClient, gmailPlugin } from 'integrate-sdk';
|
|
80
|
+
Send emails, manage labels, and search messages.
|
|
131
81
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
clientSecret: process.env.GMAIL_CLIENT_SECRET!,
|
|
137
|
-
scopes: [ // Optional, defaults to common Gmail scopes
|
|
138
|
-
'https://www.googleapis.com/auth/gmail.send',
|
|
139
|
-
'https://www.googleapis.com/auth/gmail.readonly',
|
|
140
|
-
],
|
|
141
|
-
}),
|
|
142
|
-
],
|
|
82
|
+
```typescript
|
|
83
|
+
gmailPlugin({
|
|
84
|
+
clientId: process.env.GMAIL_CLIENT_ID!,
|
|
85
|
+
clientSecret: process.env.GMAIL_CLIENT_SECRET!,
|
|
143
86
|
});
|
|
144
87
|
```
|
|
145
88
|
|
|
146
|
-
|
|
147
|
-
- `gmail_send_email`
|
|
148
|
-
- `gmail_list_emails`
|
|
149
|
-
- `gmail_get_email`
|
|
150
|
-
- `gmail_delete_email`
|
|
151
|
-
- `gmail_search_emails`
|
|
152
|
-
- `gmail_mark_as_read`
|
|
153
|
-
- `gmail_mark_as_unread`
|
|
154
|
-
- `gmail_list_labels`
|
|
155
|
-
- `gmail_create_label`
|
|
156
|
-
- And more...
|
|
89
|
+
[→ View Gmail plugin documentation](https://integrate.dev/docs/plugins/gmail)
|
|
157
90
|
|
|
158
|
-
|
|
91
|
+
### Custom Plugins
|
|
159
92
|
|
|
160
|
-
|
|
93
|
+
Create your own plugins for any service.
|
|
161
94
|
|
|
162
95
|
```typescript
|
|
163
|
-
import {
|
|
96
|
+
import { genericOAuthPlugin } from "integrate-sdk";
|
|
164
97
|
|
|
165
98
|
const slackPlugin = genericOAuthPlugin({
|
|
166
|
-
id:
|
|
167
|
-
provider:
|
|
99
|
+
id: "slack",
|
|
100
|
+
provider: "slack",
|
|
168
101
|
clientId: process.env.SLACK_CLIENT_ID!,
|
|
169
102
|
clientSecret: process.env.SLACK_CLIENT_SECRET!,
|
|
170
|
-
scopes: [
|
|
171
|
-
tools: [
|
|
172
|
-
'slack_send_message',
|
|
173
|
-
'slack_list_channels',
|
|
174
|
-
'slack_get_channel',
|
|
175
|
-
'slack_invite_user',
|
|
176
|
-
],
|
|
177
|
-
redirectUri: 'https://your-app.com/callback',
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
const client = createMCPClient({
|
|
181
|
-
plugins: [slackPlugin],
|
|
103
|
+
scopes: ["chat:write", "channels:read"],
|
|
104
|
+
tools: ["slack_send_message", "slack_list_channels"],
|
|
182
105
|
});
|
|
183
106
|
```
|
|
184
107
|
|
|
185
|
-
|
|
108
|
+
[→ Learn how to create custom plugins](https://integrate.dev/docs/plugins/custom-plugins)
|
|
186
109
|
|
|
187
|
-
|
|
110
|
+
## Vercel AI SDK Integration
|
|
188
111
|
|
|
189
|
-
|
|
190
|
-
import { createSimplePlugin } from 'integrate-sdk';
|
|
191
|
-
|
|
192
|
-
const mathPlugin = createSimplePlugin({
|
|
193
|
-
id: 'math',
|
|
194
|
-
tools: ['math_add', 'math_subtract', 'math_multiply', 'math_divide'],
|
|
195
|
-
onInit: async (client) => {
|
|
196
|
-
console.log('Math plugin initialized');
|
|
197
|
-
},
|
|
198
|
-
});
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
### Creating a Custom Plugin from Scratch
|
|
112
|
+
Give AI models access to all your integrations with built-in Vercel AI SDK support.
|
|
202
113
|
|
|
203
114
|
```typescript
|
|
204
|
-
import
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
return {
|
|
208
|
-
id: 'custom',
|
|
209
|
-
tools: ['custom_tool1', 'custom_tool2'],
|
|
210
|
-
oauth: {
|
|
211
|
-
provider: 'custom-provider',
|
|
212
|
-
clientId: config.clientId,
|
|
213
|
-
clientSecret: config.clientSecret,
|
|
214
|
-
scopes: config.scopes,
|
|
215
|
-
},
|
|
216
|
-
|
|
217
|
-
async onInit(client) {
|
|
218
|
-
// Called when plugin is initialized
|
|
219
|
-
console.log('Custom plugin initialized');
|
|
220
|
-
},
|
|
221
|
-
|
|
222
|
-
async onBeforeConnect(client) {
|
|
223
|
-
// Called before connecting to server
|
|
224
|
-
},
|
|
225
|
-
|
|
226
|
-
async onAfterConnect(client) {
|
|
227
|
-
// Called after successful connection
|
|
228
|
-
},
|
|
229
|
-
|
|
230
|
-
async onDisconnect(client) {
|
|
231
|
-
// Called when disconnecting
|
|
232
|
-
},
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
```
|
|
115
|
+
import { getVercelAITools } from "integrate-sdk";
|
|
116
|
+
import { generateText } from "ai";
|
|
117
|
+
import { openai } from "@ai-sdk/openai";
|
|
236
118
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
The SDK includes built-in support for Vercel's AI SDK, allowing you to give AI models access to all your integrations.
|
|
240
|
-
|
|
241
|
-
### Quick Example
|
|
242
|
-
|
|
243
|
-
```typescript
|
|
244
|
-
import { createMCPClient, githubPlugin, getVercelAITools } from 'integrate-sdk';
|
|
245
|
-
import { generateText } from 'ai';
|
|
246
|
-
import { openai } from '@ai-sdk/openai';
|
|
247
|
-
|
|
248
|
-
// 1. Create and connect MCP client
|
|
249
|
-
const mcpClient = createMCPClient({
|
|
250
|
-
plugins: [
|
|
251
|
-
githubPlugin({
|
|
252
|
-
clientId: process.env.GITHUB_CLIENT_ID!,
|
|
253
|
-
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
|
|
254
|
-
}),
|
|
255
|
-
],
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
await mcpClient.connect();
|
|
259
|
-
|
|
260
|
-
// 2. Get tools in Vercel AI SDK format
|
|
119
|
+
// Convert MCP tools to Vercel AI SDK format
|
|
261
120
|
const tools = getVercelAITools(mcpClient);
|
|
262
121
|
|
|
263
|
-
//
|
|
122
|
+
// Use with AI models
|
|
264
123
|
const result = await generateText({
|
|
265
|
-
model: openai(
|
|
266
|
-
prompt:
|
|
124
|
+
model: openai("gpt-5"),
|
|
125
|
+
prompt: "Create a GitHub issue about the login bug",
|
|
267
126
|
tools,
|
|
268
127
|
maxToolRoundtrips: 5,
|
|
269
128
|
});
|
|
270
|
-
|
|
271
|
-
console.log(result.text);
|
|
272
129
|
```
|
|
273
130
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
1. **`getVercelAITools(client)`** - Converts all enabled MCP tools to Vercel AI SDK format
|
|
277
|
-
2. **Automatic execution** - When the AI calls a tool, it executes through your MCP client
|
|
278
|
-
3. **Type-safe** - Full TypeScript support with proper types
|
|
279
|
-
|
|
280
|
-
### Available Functions
|
|
281
|
-
|
|
282
|
-
- **`getVercelAITools(client)`** - Get all enabled tools in Vercel AI SDK format
|
|
283
|
-
- **`convertMCPToolsToVercelAI(client)`** - Same as above, alternative name
|
|
284
|
-
- **`convertMCPToolToVercelAI(tool, client)`** - Convert a single MCP tool
|
|
285
|
-
|
|
286
|
-
See `examples/vercel-ai-integration.ts` for a complete working example.
|
|
287
|
-
|
|
288
|
-
## Advanced Usage
|
|
289
|
-
|
|
290
|
-
### Accessing OAuth Configurations
|
|
291
|
-
|
|
292
|
-
```typescript
|
|
293
|
-
// Get OAuth config for a specific plugin
|
|
294
|
-
const githubOAuth = client.getOAuthConfig('github');
|
|
295
|
-
console.log('GitHub OAuth scopes:', githubOAuth?.scopes);
|
|
296
|
-
|
|
297
|
-
// Get all OAuth configs
|
|
298
|
-
const allConfigs = client.getAllOAuthConfigs();
|
|
299
|
-
for (const [pluginId, config] of allConfigs) {
|
|
300
|
-
console.log(`${pluginId}: ${config.provider}`);
|
|
301
|
-
}
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
### Listing Available Tools
|
|
305
|
-
|
|
306
|
-
```typescript
|
|
307
|
-
await client.connect();
|
|
308
|
-
|
|
309
|
-
// Get all enabled tools (filtered by plugins)
|
|
310
|
-
const enabledTools = client.getEnabledTools();
|
|
311
|
-
console.log('Enabled tools:', enabledTools.map(t => t.name));
|
|
312
|
-
|
|
313
|
-
// Get all available tools from server
|
|
314
|
-
const allTools = client.getAvailableTools();
|
|
315
|
-
console.log('All tools:', allTools.map(t => t.name));
|
|
316
|
-
|
|
317
|
-
// Get a specific tool
|
|
318
|
-
const tool = client.getTool('github_create_issue');
|
|
319
|
-
console.log('Tool schema:', tool?.inputSchema);
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
### Handling Messages and Notifications
|
|
323
|
-
|
|
324
|
-
```typescript
|
|
325
|
-
// Listen for server messages and notifications
|
|
326
|
-
const unsubscribe = client.onMessage((message) => {
|
|
327
|
-
console.log('Received message:', message);
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
// Unsubscribe when done
|
|
331
|
-
unsubscribe();
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
### Error Handling
|
|
335
|
-
|
|
336
|
-
```typescript
|
|
337
|
-
try {
|
|
338
|
-
await client.connect();
|
|
339
|
-
const result = await client.callTool('github_create_issue', {
|
|
340
|
-
repo: 'owner/repo',
|
|
341
|
-
title: 'Bug report',
|
|
342
|
-
});
|
|
343
|
-
} catch (error) {
|
|
344
|
-
if (error.message.includes('not enabled')) {
|
|
345
|
-
console.error('Tool is not enabled. Add the appropriate plugin.');
|
|
346
|
-
} else if (error.message.includes('not available')) {
|
|
347
|
-
console.error('Tool is not available on the server.');
|
|
348
|
-
} else {
|
|
349
|
-
console.error('Unexpected error:', error);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
### Custom Headers and Timeouts
|
|
355
|
-
|
|
356
|
-
```typescript
|
|
357
|
-
const client = createMCPClient({
|
|
358
|
-
plugins: [/* ... */],
|
|
359
|
-
|
|
360
|
-
// Custom headers
|
|
361
|
-
headers: {
|
|
362
|
-
'Authorization': 'Bearer token',
|
|
363
|
-
'X-Custom-Header': 'value',
|
|
364
|
-
},
|
|
365
|
-
|
|
366
|
-
// Request timeout (default: 30000ms)
|
|
367
|
-
timeout: 60000,
|
|
368
|
-
|
|
369
|
-
// Custom client info
|
|
370
|
-
clientInfo: {
|
|
371
|
-
name: 'my-app',
|
|
372
|
-
version: '1.0.0',
|
|
373
|
-
},
|
|
374
|
-
});
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
## API Reference
|
|
378
|
-
|
|
379
|
-
### `createMCPClient(config)`
|
|
380
|
-
|
|
381
|
-
Creates a new MCP client instance.
|
|
131
|
+
[→ View Vercel AI SDK integration guide](https://integrate.dev/docs/integrations/vercel-ai)
|
|
382
132
|
|
|
383
|
-
|
|
384
|
-
- `config.plugins` (MCPPlugin[]): Array of plugins to enable
|
|
385
|
-
- `config.headers` (object, optional): Custom HTTP headers
|
|
386
|
-
- `config.timeout` (number, optional): Request timeout in milliseconds
|
|
387
|
-
- `config.clientInfo` (object, optional): Client name and version
|
|
133
|
+
## Documentation
|
|
388
134
|
|
|
389
|
-
|
|
135
|
+
For detailed guides, API reference, and examples, visit the [complete documentation](https://integrate.dev):
|
|
390
136
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
-
|
|
394
|
-
-
|
|
395
|
-
-
|
|
396
|
-
-
|
|
397
|
-
- `getEnabledTools()`: Get all enabled tools
|
|
398
|
-
- `getAvailableTools()`: Get all available tools
|
|
399
|
-
- `getOAuthConfig(pluginId)`: Get OAuth config for a plugin
|
|
400
|
-
- `getAllOAuthConfigs()`: Get all OAuth configurations
|
|
401
|
-
- `onMessage(handler)`: Register a message handler
|
|
402
|
-
- `isConnected()`: Check if connected
|
|
403
|
-
- `isInitialized()`: Check if initialized
|
|
404
|
-
|
|
405
|
-
## Architecture
|
|
406
|
-
|
|
407
|
-
The SDK is built with a modular architecture:
|
|
408
|
-
|
|
409
|
-
```
|
|
410
|
-
integrate-sdk/
|
|
411
|
-
├── src/
|
|
412
|
-
│ ├── client.ts # Main MCPClient class
|
|
413
|
-
│ ├── index.ts # Public exports
|
|
414
|
-
│ ├── config/
|
|
415
|
-
│ │ └── types.ts # Configuration types
|
|
416
|
-
│ ├── transport/
|
|
417
|
-
│ │ └── http-stream.ts # HTTP streaming transport (NDJSON)
|
|
418
|
-
│ ├── protocol/
|
|
419
|
-
│ │ ├── messages.ts # MCP message types
|
|
420
|
-
│ │ └── jsonrpc.ts # JSON-RPC implementation
|
|
421
|
-
│ └── plugins/
|
|
422
|
-
│ ├── types.ts # Plugin interface
|
|
423
|
-
│ ├── github.ts # GitHub plugin
|
|
424
|
-
│ ├── gmail.ts # Gmail plugin
|
|
425
|
-
│ └── generic.ts # Generic OAuth plugin
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
**Transport Layer:**
|
|
429
|
-
The SDK uses HTTP streaming with newline-delimited JSON (NDJSON) for bidirectional communication:
|
|
430
|
-
- Single persistent HTTP connection
|
|
431
|
-
- Messages sent as JSON followed by newline (`\n`)
|
|
432
|
-
- Automatic heartbeat to keep connection alive
|
|
433
|
-
- Compatible with MCP's `StreamableHTTPServer`
|
|
434
|
-
|
|
435
|
-
## How It Works
|
|
436
|
-
|
|
437
|
-
1. **Client Configuration**: You configure the SDK with plugins for the integrations you want to use (GitHub, Gmail, etc.)
|
|
438
|
-
2. **Connection**: The SDK connects to `https://mcp.integrate.dev/api/v1/mcp` using HTTP streaming (NDJSON)
|
|
439
|
-
3. **Tool Discovery**: The SDK fetches available tools from the server and filters them based on your enabled plugins
|
|
440
|
-
4. **OAuth Configuration**: Your OAuth credentials are stored in the client configuration (not sent to the server yet)
|
|
441
|
-
5. **Tool Calls**: When you call a tool, the SDK sends a JSON-RPC request to the server
|
|
442
|
-
6. **OAuth Flow**: The server uses your OAuth configuration to authenticate and execute the tool
|
|
443
|
-
|
|
444
|
-
## Server Information
|
|
445
|
-
|
|
446
|
-
**Endpoint:** `https://mcp.integrate.dev/api/v1/mcp`
|
|
447
|
-
**Protocol:** MCP (Model Context Protocol) over HTTP streaming
|
|
448
|
-
**Format:** Newline-delimited JSON (NDJSON)
|
|
449
|
-
**Methods:** `initialize`, `tools/list`, `tools/call`
|
|
137
|
+
- **[Getting Started](https://integrate.dev/docs/getting-started/installation)** - Installation and quick start
|
|
138
|
+
- **[Plugins](https://integrate.dev/docs/plugins)** - Built-in and custom plugins
|
|
139
|
+
- **[Vercel AI SDK](https://integrate.dev/docs/integrations/vercel-ai)** - AI model integration
|
|
140
|
+
- **[Advanced Usage](https://integrate.dev/docs/guides/advanced-usage)** - Error handling, retries, and more
|
|
141
|
+
- **[API Reference](https://integrate.dev/docs/reference/api-reference)** - Complete API documentation
|
|
142
|
+
- **[Architecture](https://integrate.dev/docs/reference/architecture)** - How the SDK works
|
|
450
143
|
|
|
451
144
|
## TypeScript Support
|
|
452
145
|
|
|
453
|
-
The SDK is built with TypeScript and provides full type safety
|
|
454
|
-
|
|
455
|
-
```typescript
|
|
456
|
-
import { createMCPClient, githubPlugin } from 'integrate-sdk';
|
|
457
|
-
import type { MCPToolCallResponse } from 'integrate-sdk';
|
|
458
|
-
|
|
459
|
-
const client = createMCPClient({
|
|
460
|
-
plugins: [
|
|
461
|
-
githubPlugin({
|
|
462
|
-
clientId: process.env.GITHUB_CLIENT_ID!,
|
|
463
|
-
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
|
|
464
|
-
}),
|
|
465
|
-
],
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
// Full type inference and IntelliSense support
|
|
469
|
-
await client.connect();
|
|
470
|
-
const result: MCPToolCallResponse = await client.callTool('github_create_issue', {
|
|
471
|
-
repo: 'owner/repo',
|
|
472
|
-
title: 'Bug report',
|
|
473
|
-
});
|
|
474
|
-
```
|
|
146
|
+
The SDK is built with TypeScript and provides full type safety with IntelliSense support out of the box.
|
|
475
147
|
|
|
476
148
|
## Contributing
|
|
477
149
|
|
|
478
|
-
Contributions are welcome! Please
|
|
150
|
+
Contributions are welcome! Please check the [issues](https://github.com/Revyo/integrate-sdk/issues) for ways to contribute.
|
|
479
151
|
|
|
480
|
-
##
|
|
152
|
+
## Testing
|
|
481
153
|
|
|
482
|
-
```
|
|
483
|
-
tests/
|
|
484
|
-
├── protocol/ # Protocol and JSON-RPC tests
|
|
485
|
-
│ └── jsonrpc.test.ts
|
|
486
|
-
├── plugins/ # Plugin system tests
|
|
487
|
-
│ └── plugin-system.test.ts
|
|
488
|
-
├── client/ # Client functionality tests
|
|
489
|
-
│ └── client.test.ts
|
|
490
|
-
├── integration/ # Integration tests with mock server
|
|
491
|
-
│ ├── mock-server.ts
|
|
492
|
-
│ └── integration.test.ts
|
|
493
|
-
├── setup.ts # Test setup and utilities
|
|
494
|
-
└── README.md # This file
|
|
495
|
-
```
|
|
496
|
-
|
|
497
|
-
## Running Tests
|
|
498
|
-
|
|
499
|
-
### All Tests
|
|
500
154
|
```bash
|
|
155
|
+
# Run all tests
|
|
501
156
|
bun test
|
|
502
|
-
```
|
|
503
157
|
|
|
504
|
-
|
|
505
|
-
```bash
|
|
506
|
-
bun run test:unit
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
### Integration Tests Only
|
|
510
|
-
```bash
|
|
511
|
-
bun run test:integration
|
|
512
|
-
```
|
|
513
|
-
|
|
514
|
-
### Watch Mode
|
|
515
|
-
```bash
|
|
516
|
-
bun run test:watch
|
|
517
|
-
```
|
|
518
|
-
|
|
519
|
-
### With Coverage
|
|
520
|
-
```bash
|
|
158
|
+
# Run with coverage
|
|
521
159
|
bun run test:coverage
|
|
522
160
|
```
|
|
523
161
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
### 1. Protocol Tests (`tests/protocol/`)
|
|
527
|
-
Tests for JSON-RPC 2.0 protocol implementation:
|
|
528
|
-
- Request/response formatting
|
|
529
|
-
- Notification handling
|
|
530
|
-
- Error responses
|
|
531
|
-
- Message parsing and serialization
|
|
532
|
-
- ID generation
|
|
533
|
-
|
|
534
|
-
### 2. Plugin System Tests (`tests/plugins/`)
|
|
535
|
-
Tests for the plugin architecture:
|
|
536
|
-
- GitHub plugin configuration
|
|
537
|
-
- Gmail plugin configuration
|
|
538
|
-
- Generic OAuth plugin creation
|
|
539
|
-
- Simple plugin creation
|
|
540
|
-
- OAuth config type guards
|
|
541
|
-
- Plugin lifecycle hooks
|
|
542
|
-
|
|
543
|
-
### 3. Client Tests (`tests/client/`)
|
|
544
|
-
Tests for the main MCP client:
|
|
545
|
-
- Client creation and configuration
|
|
546
|
-
- Plugin initialization
|
|
547
|
-
- OAuth configuration management
|
|
548
|
-
- Tool management
|
|
549
|
-
- Connection state tracking
|
|
550
|
-
- Error handling
|
|
551
|
-
- Message handlers
|
|
552
|
-
|
|
553
|
-
### 4. Integration Tests (`tests/integration/`)
|
|
554
|
-
End-to-end tests with a mock MCP server:
|
|
555
|
-
- Connection establishment
|
|
556
|
-
- Tool discovery
|
|
557
|
-
- Tool filtering by plugins
|
|
558
|
-
- Tool invocation
|
|
559
|
-
- Plugin lifecycle hooks
|
|
560
|
-
- Concurrent requests
|
|
561
|
-
- Error scenarios
|
|
562
|
-
- Connection timeout
|
|
563
|
-
|
|
564
|
-
## Mock Server
|
|
565
|
-
|
|
566
|
-
The integration tests use a mock MCP server that:
|
|
567
|
-
- Implements HTTP streaming with NDJSON
|
|
568
|
-
- Supports `initialize`, `tools/list`, and `tools/call` methods
|
|
569
|
-
- Returns configurable tools
|
|
570
|
-
- Handles heartbeat/ping messages
|
|
571
|
-
- Runs on a random port to avoid conflicts
|
|
572
|
-
|
|
573
|
-
Example usage:
|
|
574
|
-
```typescript
|
|
575
|
-
import { MockMCPServer } from './tests/integration/mock-server';
|
|
576
|
-
|
|
577
|
-
const server = new MockMCPServer({
|
|
578
|
-
port: 3456,
|
|
579
|
-
tools: [
|
|
580
|
-
{
|
|
581
|
-
name: 'test/echo',
|
|
582
|
-
description: 'Echo test tool',
|
|
583
|
-
inputSchema: { /* ... */ }
|
|
584
|
-
}
|
|
585
|
-
]
|
|
586
|
-
});
|
|
587
|
-
|
|
588
|
-
await server.start();
|
|
589
|
-
// Run tests...
|
|
590
|
-
await server.stop();
|
|
591
|
-
```
|
|
592
|
-
|
|
593
|
-
## Writing New Tests
|
|
594
|
-
|
|
595
|
-
### Unit Test Example
|
|
596
|
-
|
|
597
|
-
```typescript
|
|
598
|
-
import { describe, test, expect } from "bun:test";
|
|
599
|
-
import { myFunction } from "../../src/module.js";
|
|
600
|
-
|
|
601
|
-
describe("My Module", () => {
|
|
602
|
-
test("does something correctly", () => {
|
|
603
|
-
const result = myFunction("input");
|
|
604
|
-
expect(result).toBe("expected output");
|
|
605
|
-
});
|
|
606
|
-
});
|
|
607
|
-
```
|
|
608
|
-
|
|
609
|
-
### Integration Test Example
|
|
610
|
-
|
|
611
|
-
```typescript
|
|
612
|
-
import { describe, test, expect, beforeAll, afterAll } from "bun:test";
|
|
613
|
-
import { createMCPClient } from "../../src/client.js";
|
|
614
|
-
import { MockMCPServer } from "./mock-server.js";
|
|
615
|
-
|
|
616
|
-
describe("Integration Test", () => {
|
|
617
|
-
let server: MockMCPServer;
|
|
618
|
-
|
|
619
|
-
beforeAll(async () => {
|
|
620
|
-
server = new MockMCPServer({ port: 3456 });
|
|
621
|
-
await server.start();
|
|
622
|
-
});
|
|
623
|
-
|
|
624
|
-
afterAll(async () => {
|
|
625
|
-
await server.stop();
|
|
626
|
-
});
|
|
627
|
-
|
|
628
|
-
test("connects and calls tool", async () => {
|
|
629
|
-
const client = createMCPClient({
|
|
630
|
-
plugins: [/* ... */],
|
|
631
|
-
});
|
|
632
|
-
|
|
633
|
-
await client.connect();
|
|
634
|
-
const result = await client.callTool("test/tool");
|
|
635
|
-
expect(result).toBeDefined();
|
|
636
|
-
await client.disconnect();
|
|
637
|
-
});
|
|
638
|
-
});
|
|
639
|
-
```
|
|
640
|
-
|
|
641
|
-
## Test Coverage
|
|
642
|
-
|
|
643
|
-
The test suite covers:
|
|
644
|
-
- ✅ JSON-RPC protocol implementation
|
|
645
|
-
- ✅ Plugin system and configuration
|
|
646
|
-
- ✅ Client initialization and lifecycle
|
|
647
|
-
- ✅ Tool discovery and filtering
|
|
648
|
-
- ✅ Tool invocation
|
|
649
|
-
- ✅ OAuth configuration management
|
|
650
|
-
- ✅ Error handling
|
|
651
|
-
- ✅ Connection management
|
|
652
|
-
- ✅ Concurrent requests
|
|
653
|
-
- ✅ Plugin lifecycle hooks
|
|
654
|
-
|
|
655
|
-
## Debugging Tests
|
|
656
|
-
|
|
657
|
-
Run tests with debug output:
|
|
658
|
-
```bash
|
|
659
|
-
DEBUG=1 bun test
|
|
660
|
-
```
|
|
661
|
-
|
|
662
|
-
Run specific test file:
|
|
663
|
-
```bash
|
|
664
|
-
bun test tests/protocol/jsonrpc.test.ts
|
|
665
|
-
```
|
|
666
|
-
|
|
667
|
-
Run specific test:
|
|
668
|
-
```bash
|
|
669
|
-
bun test -t "creates valid JSON-RPC request"
|
|
670
|
-
```
|
|
671
|
-
|
|
672
|
-
## Continuous Integration
|
|
673
|
-
|
|
674
|
-
Tests run automatically on:
|
|
675
|
-
- Push to `main` or `develop` branches
|
|
676
|
-
- Pull requests to `main` or `develop`
|
|
677
|
-
|
|
678
|
-
The CI pipeline runs:
|
|
679
|
-
1. Type checking
|
|
680
|
-
2. Unit tests
|
|
681
|
-
3. Integration tests
|
|
682
|
-
4. Build verification
|
|
683
|
-
|
|
684
|
-
See `.github/workflows/test.yml` for details.
|
|
685
|
-
|
|
686
|
-
## Common Issues
|
|
687
|
-
|
|
688
|
-
### Port Already in Use
|
|
689
|
-
Integration tests use port 3456. If this conflicts, modify `MockMCPServer` constructor.
|
|
690
|
-
|
|
691
|
-
### Test Timeouts
|
|
692
|
-
Integration tests have 10s timeout. Increase if needed:
|
|
693
|
-
```typescript
|
|
694
|
-
test("my test", async () => {
|
|
695
|
-
// test code
|
|
696
|
-
}, 20000); // 20 second timeout
|
|
697
|
-
```
|
|
698
|
-
|
|
699
|
-
### Console Logs
|
|
700
|
-
Console logs are suppressed during tests unless `DEBUG=1` is set.
|
|
701
|
-
|
|
702
|
-
## Contributing
|
|
703
|
-
|
|
704
|
-
When adding new features:
|
|
705
|
-
1. Write unit tests for individual components
|
|
706
|
-
2. Write integration tests for end-to-end flows
|
|
707
|
-
3. Ensure all tests pass before submitting PR
|
|
708
|
-
4. Maintain test coverage above 80%
|
|
709
|
-
|
|
162
|
+
See the `tests/` directory for unit and integration test examples.
|
|
710
163
|
|
|
164
|
+
## License
|
|
711
165
|
|
|
166
|
+
MIT © [Revyo](https://github.com/Revyo)
|
package/dist/client.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import type { MCPTool, MCPToolCallResponse } from "./protocol/messages.js";
|
|
6
6
|
import type { MCPPlugin, OAuthConfig } from "./plugins/types.js";
|
|
7
7
|
import type { MCPClientConfig } from "./config/types.js";
|
|
8
|
+
import { type AuthenticationError } from "./errors.js";
|
|
8
9
|
/**
|
|
9
10
|
* Tool invocation options
|
|
10
11
|
*/
|
|
@@ -26,6 +27,9 @@ export declare class MCPClient<TPlugins extends readonly MCPPlugin[] = readonly
|
|
|
26
27
|
private enabledToolNames;
|
|
27
28
|
private initialized;
|
|
28
29
|
private clientInfo;
|
|
30
|
+
private onReauthRequired?;
|
|
31
|
+
private maxReauthRetries;
|
|
32
|
+
private authState;
|
|
29
33
|
constructor(config: MCPClientConfig<TPlugins>);
|
|
30
34
|
/**
|
|
31
35
|
* Initialize all plugins
|
|
@@ -44,9 +48,17 @@ export declare class MCPClient<TPlugins extends readonly MCPPlugin[] = readonly
|
|
|
44
48
|
*/
|
|
45
49
|
private discoverTools;
|
|
46
50
|
/**
|
|
47
|
-
* Call a tool by name
|
|
51
|
+
* Call a tool by name with automatic retry on authentication failure
|
|
48
52
|
*/
|
|
49
53
|
callTool(name: string, args?: Record<string, unknown>): Promise<MCPToolCallResponse>;
|
|
54
|
+
/**
|
|
55
|
+
* Internal method to call a tool with retry logic
|
|
56
|
+
*/
|
|
57
|
+
private callToolWithRetry;
|
|
58
|
+
/**
|
|
59
|
+
* Get the OAuth provider for a given tool
|
|
60
|
+
*/
|
|
61
|
+
private getProviderForTool;
|
|
50
62
|
/**
|
|
51
63
|
* Get a tool by name
|
|
52
64
|
*/
|
|
@@ -83,6 +95,22 @@ export declare class MCPClient<TPlugins extends readonly MCPPlugin[] = readonly
|
|
|
83
95
|
* Check if client is initialized
|
|
84
96
|
*/
|
|
85
97
|
isInitialized(): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Get authentication state for a specific provider
|
|
100
|
+
*/
|
|
101
|
+
getAuthState(provider: string): {
|
|
102
|
+
authenticated: boolean;
|
|
103
|
+
lastError?: AuthenticationError;
|
|
104
|
+
} | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* Check if a specific provider is authenticated
|
|
107
|
+
*/
|
|
108
|
+
isProviderAuthenticated(provider: string): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Manually trigger re-authentication for a specific provider
|
|
111
|
+
* Useful if you want to proactively refresh tokens
|
|
112
|
+
*/
|
|
113
|
+
reauthenticate(provider: string): Promise<boolean>;
|
|
86
114
|
}
|
|
87
115
|
/**
|
|
88
116
|
* Create a new MCP Client instance
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACV,OAAO,EAEP,mBAAmB,EAIpB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACV,OAAO,EAEP,mBAAmB,EAIpB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,aAAa,CAAC;AAOrB;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED;;;;GAIG;AACH,qBAAa,SAAS,CAAC,QAAQ,SAAS,SAAS,SAAS,EAAE,GAAG,SAAS,SAAS,EAAE;IACjF,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,cAAc,CAAmC;IACzD,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,gBAAgB,CAAC,CAAgB;IACzC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,SAAS,CAAuF;gBAE5F,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC;IA+B7C;;OAEG;YACW,iBAAiB;IAQ/B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB9B;;OAEG;YACW,UAAU;IAkBxB;;OAEG;YACW,aAAa;IAoB3B;;OAEG;IACG,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,mBAAmB,CAAC;IAI/B;;OAEG;YACW,iBAAiB;IA4E/B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAS1B;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI1C;;OAEG;IACH,iBAAiB,IAAI,OAAO,EAAE;IAI9B;;OAEG;IACH,eAAe,IAAI,OAAO,EAAE;IAM5B;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAKzD;;OAEG;IACH,kBAAkB,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC;IAU9C;;OAEG;IACH,SAAS,CACP,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAClC,MAAM,IAAI;IAIb;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAYjC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG;QAAE,aAAa,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,mBAAmB,CAAA;KAAE,GAAG,SAAS;IAIvG;;OAEG;IACH,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIlD;;;OAGG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CA2BzD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,QAAQ,SAAS,SAAS,SAAS,EAAE,EACnE,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,GAChC,SAAS,CAAC,QAAQ,CAAC,CAErB"}
|
package/dist/config/types.d.ts
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
3
3
|
* Type-safe configuration with inference
|
|
4
4
|
*/
|
|
5
5
|
import type { MCPPlugin } from "../plugins/types.js";
|
|
6
|
+
import type { AuthenticationError } from "../errors.js";
|
|
7
|
+
/**
|
|
8
|
+
* Re-authentication context provided to the callback
|
|
9
|
+
*/
|
|
10
|
+
export interface ReauthContext {
|
|
11
|
+
/** The plugin/provider that needs re-authentication */
|
|
12
|
+
provider: string;
|
|
13
|
+
/** The error that triggered re-authentication */
|
|
14
|
+
error: AuthenticationError;
|
|
15
|
+
/** The tool name that was being called (if applicable) */
|
|
16
|
+
toolName?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Re-authentication handler function
|
|
20
|
+
* Called when authentication fails and user needs to re-authenticate
|
|
21
|
+
* Should return true if re-authentication was successful, false otherwise
|
|
22
|
+
*/
|
|
23
|
+
export type ReauthHandler = (context: ReauthContext) => Promise<boolean> | boolean;
|
|
6
24
|
/**
|
|
7
25
|
* Main client configuration
|
|
8
26
|
*/
|
|
@@ -18,6 +36,33 @@ export interface MCPClientConfig<TPlugins extends readonly MCPPlugin[]> {
|
|
|
18
36
|
name: string;
|
|
19
37
|
version: string;
|
|
20
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* Handler called when authentication fails and re-authentication is needed
|
|
41
|
+
* This is typically called when OAuth tokens expire or become invalid
|
|
42
|
+
*
|
|
43
|
+
* @param context - Information about the authentication failure
|
|
44
|
+
* @returns Promise<boolean> - true if re-authentication was successful, false otherwise
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const client = createMCPClient({
|
|
49
|
+
* plugins: [githubPlugin(...)],
|
|
50
|
+
* onReauthRequired: async (context) => {
|
|
51
|
+
* console.log(`Re-auth needed for ${context.provider}`);
|
|
52
|
+
* // Trigger your OAuth flow here
|
|
53
|
+
* // Return true if successful, false otherwise
|
|
54
|
+
* return await triggerOAuthFlow(context.provider);
|
|
55
|
+
* }
|
|
56
|
+
* });
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
onReauthRequired?: ReauthHandler;
|
|
60
|
+
/**
|
|
61
|
+
* Maximum number of automatic retry attempts when authentication fails
|
|
62
|
+
* Default: 1 (one retry after re-authentication)
|
|
63
|
+
* Set to 0 to disable automatic retries
|
|
64
|
+
*/
|
|
65
|
+
maxReauthRetries?: number;
|
|
21
66
|
}
|
|
22
67
|
/**
|
|
23
68
|
* Helper type to infer enabled tools from plugins
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,KAAK,EAAE,mBAAmB,CAAC;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAEnF;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,QAAQ,SAAS,SAAS,SAAS,EAAE;IACpE,iCAAiC;IACjC,OAAO,EAAE,QAAQ,CAAC;IAElB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,yBAAyB;IACzB,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF;;;;;;;;;;;;;;;;;;;OAmBG;IACH,gBAAgB,CAAC,EAAE,aAAa,CAAC;IAEjC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,QAAQ,SAAS,SAAS,SAAS,EAAE,IACjE,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpC;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAAC,QAAQ,SAAS,SAAS,SAAS,EAAE,IAAI;KACnE,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;CAC/C,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error types for the Integrate SDK
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Base error class for all SDK errors
|
|
6
|
+
*/
|
|
7
|
+
export declare class IntegrateSDKError extends Error {
|
|
8
|
+
constructor(message: string);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Error thrown when authentication fails or tokens are invalid
|
|
12
|
+
*/
|
|
13
|
+
export declare class AuthenticationError extends IntegrateSDKError {
|
|
14
|
+
readonly statusCode?: number;
|
|
15
|
+
readonly provider?: string;
|
|
16
|
+
constructor(message: string, statusCode?: number, provider?: string);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Error thrown when access is forbidden (insufficient permissions)
|
|
20
|
+
*/
|
|
21
|
+
export declare class AuthorizationError extends IntegrateSDKError {
|
|
22
|
+
readonly statusCode?: number;
|
|
23
|
+
readonly requiredScopes?: string[];
|
|
24
|
+
constructor(message: string, statusCode?: number, requiredScopes?: string[]);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Error thrown when OAuth tokens have expired and need to be refreshed
|
|
28
|
+
*/
|
|
29
|
+
export declare class TokenExpiredError extends AuthenticationError {
|
|
30
|
+
constructor(message: string, provider?: string);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Error thrown when a connection to the server fails
|
|
34
|
+
*/
|
|
35
|
+
export declare class ConnectionError extends IntegrateSDKError {
|
|
36
|
+
readonly statusCode?: number;
|
|
37
|
+
constructor(message: string, statusCode?: number);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Error thrown when a tool call fails
|
|
41
|
+
*/
|
|
42
|
+
export declare class ToolCallError extends IntegrateSDKError {
|
|
43
|
+
readonly toolName: string;
|
|
44
|
+
readonly originalError?: unknown;
|
|
45
|
+
constructor(message: string, toolName: string, originalError?: unknown);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Helper function to determine if an error is an authentication error
|
|
49
|
+
*/
|
|
50
|
+
export declare function isAuthError(error: unknown): error is AuthenticationError;
|
|
51
|
+
/**
|
|
52
|
+
* Helper function to determine if an error is a token expired error
|
|
53
|
+
*/
|
|
54
|
+
export declare function isTokenExpiredError(error: unknown): error is TokenExpiredError;
|
|
55
|
+
/**
|
|
56
|
+
* Helper function to determine if an error is an authorization error
|
|
57
|
+
*/
|
|
58
|
+
export declare function isAuthorizationError(error: unknown): error is AuthorizationError;
|
|
59
|
+
/**
|
|
60
|
+
* Helper function to parse error responses from the MCP server
|
|
61
|
+
* and convert them to appropriate error types
|
|
62
|
+
*/
|
|
63
|
+
export declare function parseServerError(error: any, context?: {
|
|
64
|
+
toolName?: string;
|
|
65
|
+
provider?: string;
|
|
66
|
+
}): IntegrateSDKError;
|
|
67
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,iBAAiB;IACxD,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpC,SAAgB,QAAQ,CAAC,EAAE,MAAM,CAAC;gBAEtB,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;CAMpE;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,iBAAiB;IACvD,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpC,SAAgB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;gBAE9B,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE;CAM5E;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,mBAAmB;gBAC5C,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;CAI/C;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,iBAAiB;IACpD,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;gBAExB,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAKjD;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,iBAAiB;IAClD,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,aAAa,CAAC,EAAE,OAAO,CAAC;gBAE5B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,OAAO;CAMvE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAExE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB,CAEhF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,GAAG,EACV,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD,iBAAiB,CA+FnB"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { MCPClient, createMCPClient } from "./client.js";
|
|
6
6
|
export type { ToolInvocationOptions } from "./client.js";
|
|
7
|
-
export type { MCPClientConfig } from "./config/types.js";
|
|
7
|
+
export type { MCPClientConfig, ReauthContext, ReauthHandler } from "./config/types.js";
|
|
8
|
+
export { IntegrateSDKError, AuthenticationError, AuthorizationError, TokenExpiredError, ConnectionError, ToolCallError, isAuthError, isTokenExpiredError, isAuthorizationError, parseServerError, } from "./errors.js";
|
|
8
9
|
export type { MCPPlugin, OAuthConfig, ExtractPluginIds, ExtractPluginTools, } from "./plugins/types.js";
|
|
9
10
|
export { githubPlugin } from "./plugins/github.js";
|
|
10
11
|
export type { GitHubPluginConfig, GitHubTools } from "./plugins/github.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAGzD,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAGzD,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvF,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAGrB,YAAY,EACV,SAAS,EACT,WAAW,EACX,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAExE,OAAO,EACL,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAGrE,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAGhE,YAAY,EACV,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,OAAO,EACP,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,YAAY,EACV,cAAc,EACd,2BAA2B,GAC5B,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,153 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, {
|
|
5
|
+
get: all[name],
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
set: (newValue) => all[name] = () => newValue
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
|
+
|
|
13
|
+
// src/errors.ts
|
|
14
|
+
var exports_errors = {};
|
|
15
|
+
__export(exports_errors, {
|
|
16
|
+
parseServerError: () => parseServerError,
|
|
17
|
+
isTokenExpiredError: () => isTokenExpiredError,
|
|
18
|
+
isAuthorizationError: () => isAuthorizationError,
|
|
19
|
+
isAuthError: () => isAuthError,
|
|
20
|
+
ToolCallError: () => ToolCallError,
|
|
21
|
+
TokenExpiredError: () => TokenExpiredError,
|
|
22
|
+
IntegrateSDKError: () => IntegrateSDKError,
|
|
23
|
+
ConnectionError: () => ConnectionError,
|
|
24
|
+
AuthorizationError: () => AuthorizationError,
|
|
25
|
+
AuthenticationError: () => AuthenticationError
|
|
26
|
+
});
|
|
27
|
+
function isAuthError(error) {
|
|
28
|
+
return error instanceof AuthenticationError;
|
|
29
|
+
}
|
|
30
|
+
function isTokenExpiredError(error) {
|
|
31
|
+
return error instanceof TokenExpiredError;
|
|
32
|
+
}
|
|
33
|
+
function isAuthorizationError(error) {
|
|
34
|
+
return error instanceof AuthorizationError;
|
|
35
|
+
}
|
|
36
|
+
function parseServerError(error, context) {
|
|
37
|
+
if (error && typeof error === "object" && "jsonrpcError" in error) {
|
|
38
|
+
const jsonrpcError = error.jsonrpcError;
|
|
39
|
+
if (jsonrpcError && typeof jsonrpcError === "object") {
|
|
40
|
+
return parseServerError(jsonrpcError, context);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (error && typeof error === "object" && "code" in error && "message" in error) {
|
|
44
|
+
const code = error.code;
|
|
45
|
+
const message = error.message || "Unknown error";
|
|
46
|
+
if (code === -32600) {
|
|
47
|
+
return new IntegrateSDKError(`Invalid request: ${message}`);
|
|
48
|
+
}
|
|
49
|
+
if (code === -32601) {
|
|
50
|
+
return new IntegrateSDKError(`Method not found: ${message}`);
|
|
51
|
+
}
|
|
52
|
+
if (code === -32602) {
|
|
53
|
+
return new IntegrateSDKError(`Invalid params: ${message}`);
|
|
54
|
+
}
|
|
55
|
+
if (code === 401 || code === -32001) {
|
|
56
|
+
if (message.toLowerCase().includes("expired") || message.toLowerCase().includes("token")) {
|
|
57
|
+
return new TokenExpiredError(message, context?.provider);
|
|
58
|
+
}
|
|
59
|
+
return new AuthenticationError(message, 401, context?.provider);
|
|
60
|
+
}
|
|
61
|
+
if (code === 403 || code === -32002) {
|
|
62
|
+
return new AuthorizationError(message, 403);
|
|
63
|
+
}
|
|
64
|
+
if (context?.toolName) {
|
|
65
|
+
return new ToolCallError(message, context.toolName, error);
|
|
66
|
+
}
|
|
67
|
+
return new IntegrateSDKError(message);
|
|
68
|
+
}
|
|
69
|
+
if (error instanceof Error) {
|
|
70
|
+
const message = error.message;
|
|
71
|
+
const statusCode = error.statusCode;
|
|
72
|
+
if (statusCode === 401) {
|
|
73
|
+
if (message.toLowerCase().includes("expired") || message.toLowerCase().includes("token")) {
|
|
74
|
+
return new TokenExpiredError(message, context?.provider);
|
|
75
|
+
}
|
|
76
|
+
return new AuthenticationError(message, 401, context?.provider);
|
|
77
|
+
}
|
|
78
|
+
if (statusCode === 403) {
|
|
79
|
+
return new AuthorizationError(message, 403);
|
|
80
|
+
}
|
|
81
|
+
if (message.includes("401") || message.includes("Unauthorized") || message.includes("unauthenticated")) {
|
|
82
|
+
if (message.toLowerCase().includes("expired") || message.toLowerCase().includes("token")) {
|
|
83
|
+
return new TokenExpiredError(message, context?.provider);
|
|
84
|
+
}
|
|
85
|
+
return new AuthenticationError(message, 401, context?.provider);
|
|
86
|
+
}
|
|
87
|
+
if (message.includes("403") || message.includes("Forbidden") || message.includes("unauthorized")) {
|
|
88
|
+
return new AuthorizationError(message, 403);
|
|
89
|
+
}
|
|
90
|
+
if (context?.toolName) {
|
|
91
|
+
return new ToolCallError(message, context.toolName, error);
|
|
92
|
+
}
|
|
93
|
+
return new IntegrateSDKError(message);
|
|
94
|
+
}
|
|
95
|
+
return new IntegrateSDKError(String(error));
|
|
96
|
+
}
|
|
97
|
+
var IntegrateSDKError, AuthenticationError, AuthorizationError, TokenExpiredError, ConnectionError, ToolCallError;
|
|
98
|
+
var init_errors = __esm(() => {
|
|
99
|
+
IntegrateSDKError = class IntegrateSDKError extends Error {
|
|
100
|
+
constructor(message) {
|
|
101
|
+
super(message);
|
|
102
|
+
this.name = "IntegrateSDKError";
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
AuthenticationError = class AuthenticationError extends IntegrateSDKError {
|
|
106
|
+
statusCode;
|
|
107
|
+
provider;
|
|
108
|
+
constructor(message, statusCode, provider) {
|
|
109
|
+
super(message);
|
|
110
|
+
this.name = "AuthenticationError";
|
|
111
|
+
this.statusCode = statusCode;
|
|
112
|
+
this.provider = provider;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
AuthorizationError = class AuthorizationError extends IntegrateSDKError {
|
|
116
|
+
statusCode;
|
|
117
|
+
requiredScopes;
|
|
118
|
+
constructor(message, statusCode, requiredScopes) {
|
|
119
|
+
super(message);
|
|
120
|
+
this.name = "AuthorizationError";
|
|
121
|
+
this.statusCode = statusCode;
|
|
122
|
+
this.requiredScopes = requiredScopes;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
TokenExpiredError = class TokenExpiredError extends AuthenticationError {
|
|
126
|
+
constructor(message, provider) {
|
|
127
|
+
super(message, 401, provider);
|
|
128
|
+
this.name = "TokenExpiredError";
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
ConnectionError = class ConnectionError extends IntegrateSDKError {
|
|
132
|
+
statusCode;
|
|
133
|
+
constructor(message, statusCode) {
|
|
134
|
+
super(message);
|
|
135
|
+
this.name = "ConnectionError";
|
|
136
|
+
this.statusCode = statusCode;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
ToolCallError = class ToolCallError extends IntegrateSDKError {
|
|
140
|
+
toolName;
|
|
141
|
+
originalError;
|
|
142
|
+
constructor(message, toolName, originalError) {
|
|
143
|
+
super(message);
|
|
144
|
+
this.name = "ToolCallError";
|
|
145
|
+
this.toolName = toolName;
|
|
146
|
+
this.originalError = originalError;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
|
|
1
151
|
// src/protocol/jsonrpc.ts
|
|
2
152
|
function parseMessage(message) {
|
|
3
153
|
try {
|
|
@@ -55,7 +205,9 @@ class HttpSessionTransport {
|
|
|
55
205
|
});
|
|
56
206
|
clearTimeout(timeoutId);
|
|
57
207
|
if (!response.ok) {
|
|
58
|
-
|
|
208
|
+
const error = new Error(`Request failed: ${response.statusText}`);
|
|
209
|
+
error.statusCode = response.status;
|
|
210
|
+
throw error;
|
|
59
211
|
}
|
|
60
212
|
if (!this.sessionId) {
|
|
61
213
|
const sid = response.headers.get("mcp-session-id");
|
|
@@ -67,11 +219,25 @@ class HttpSessionTransport {
|
|
|
67
219
|
}
|
|
68
220
|
const jsonResponse = await response.json();
|
|
69
221
|
if ("error" in jsonResponse) {
|
|
70
|
-
|
|
222
|
+
const error = new Error(`JSON-RPC Error ${jsonResponse.error.code}: ${jsonResponse.error.message}`);
|
|
223
|
+
error.code = jsonResponse.error.code;
|
|
224
|
+
if (jsonResponse.error.data) {
|
|
225
|
+
error.data = jsonResponse.error.data;
|
|
226
|
+
}
|
|
227
|
+
error.jsonrpcError = jsonResponse.error;
|
|
228
|
+
throw error;
|
|
71
229
|
}
|
|
72
230
|
return jsonResponse.result;
|
|
73
231
|
} catch (error) {
|
|
74
|
-
|
|
232
|
+
if (error instanceof Error) {
|
|
233
|
+
if (error.name === "AbortError") {
|
|
234
|
+
const timeoutError = new Error("Request timeout");
|
|
235
|
+
timeoutError.code = -32000;
|
|
236
|
+
throw timeoutError;
|
|
237
|
+
}
|
|
238
|
+
throw error;
|
|
239
|
+
}
|
|
240
|
+
throw new Error(String(error));
|
|
75
241
|
}
|
|
76
242
|
}
|
|
77
243
|
async startSSEListener() {
|
|
@@ -184,6 +350,7 @@ var MCPMethod;
|
|
|
184
350
|
})(MCPMethod ||= {});
|
|
185
351
|
|
|
186
352
|
// src/client.ts
|
|
353
|
+
init_errors();
|
|
187
354
|
var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
|
|
188
355
|
|
|
189
356
|
class MCPClient {
|
|
@@ -193,6 +360,9 @@ class MCPClient {
|
|
|
193
360
|
enabledToolNames = new Set;
|
|
194
361
|
initialized = false;
|
|
195
362
|
clientInfo;
|
|
363
|
+
onReauthRequired;
|
|
364
|
+
maxReauthRetries;
|
|
365
|
+
authState = new Map;
|
|
196
366
|
constructor(config) {
|
|
197
367
|
this.transport = new HttpSessionTransport({
|
|
198
368
|
url: MCP_SERVER_URL,
|
|
@@ -204,10 +374,15 @@ class MCPClient {
|
|
|
204
374
|
name: "integrate-sdk",
|
|
205
375
|
version: "0.1.0"
|
|
206
376
|
};
|
|
377
|
+
this.onReauthRequired = config.onReauthRequired;
|
|
378
|
+
this.maxReauthRetries = config.maxReauthRetries ?? 1;
|
|
207
379
|
for (const plugin of this.plugins) {
|
|
208
380
|
for (const toolName of plugin.tools) {
|
|
209
381
|
this.enabledToolNames.add(toolName);
|
|
210
382
|
}
|
|
383
|
+
if (plugin.oauth) {
|
|
384
|
+
this.authState.set(plugin.oauth.provider, { authenticated: true });
|
|
385
|
+
}
|
|
211
386
|
}
|
|
212
387
|
this.initializePlugins();
|
|
213
388
|
}
|
|
@@ -254,6 +429,9 @@ class MCPClient {
|
|
|
254
429
|
console.log(`Discovered ${response.tools.length} tools, ${enabledTools.length} enabled by plugins`);
|
|
255
430
|
}
|
|
256
431
|
async callTool(name, args) {
|
|
432
|
+
return await this.callToolWithRetry(name, args, 0);
|
|
433
|
+
}
|
|
434
|
+
async callToolWithRetry(name, args, retryCount = 0) {
|
|
257
435
|
if (!this.initialized) {
|
|
258
436
|
throw new Error("Client not initialized. Call connect() first.");
|
|
259
437
|
}
|
|
@@ -267,7 +445,44 @@ class MCPClient {
|
|
|
267
445
|
name,
|
|
268
446
|
arguments: args
|
|
269
447
|
};
|
|
270
|
-
|
|
448
|
+
try {
|
|
449
|
+
const response = await this.transport.sendRequest("tools/call" /* TOOLS_CALL */, params);
|
|
450
|
+
const provider = this.getProviderForTool(name);
|
|
451
|
+
if (provider) {
|
|
452
|
+
this.authState.set(provider, { authenticated: true });
|
|
453
|
+
}
|
|
454
|
+
return response;
|
|
455
|
+
} catch (error) {
|
|
456
|
+
const provider = this.getProviderForTool(name);
|
|
457
|
+
const parsedError = parseServerError(error, { toolName: name, provider });
|
|
458
|
+
if (isAuthError(parsedError) && retryCount < this.maxReauthRetries) {
|
|
459
|
+
if (provider) {
|
|
460
|
+
this.authState.set(provider, {
|
|
461
|
+
authenticated: false,
|
|
462
|
+
lastError: parsedError
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
if (this.onReauthRequired && provider) {
|
|
466
|
+
const reauthSuccess = await this.onReauthRequired({
|
|
467
|
+
provider,
|
|
468
|
+
error: parsedError,
|
|
469
|
+
toolName: name
|
|
470
|
+
});
|
|
471
|
+
if (reauthSuccess) {
|
|
472
|
+
return await this.callToolWithRetry(name, args, retryCount + 1);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
throw parsedError;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
getProviderForTool(toolName) {
|
|
480
|
+
for (const plugin of this.plugins) {
|
|
481
|
+
if (plugin.tools.includes(toolName) && plugin.oauth) {
|
|
482
|
+
return plugin.oauth.provider;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
return;
|
|
271
486
|
}
|
|
272
487
|
getTool(name) {
|
|
273
488
|
return this.availableTools.get(name);
|
|
@@ -309,10 +524,38 @@ class MCPClient {
|
|
|
309
524
|
isInitialized() {
|
|
310
525
|
return this.initialized;
|
|
311
526
|
}
|
|
527
|
+
getAuthState(provider) {
|
|
528
|
+
return this.authState.get(provider);
|
|
529
|
+
}
|
|
530
|
+
isProviderAuthenticated(provider) {
|
|
531
|
+
return this.authState.get(provider)?.authenticated ?? false;
|
|
532
|
+
}
|
|
533
|
+
async reauthenticate(provider) {
|
|
534
|
+
const state = this.authState.get(provider);
|
|
535
|
+
if (!state) {
|
|
536
|
+
throw new Error(`Provider "${provider}" not found in configured plugins`);
|
|
537
|
+
}
|
|
538
|
+
if (!this.onReauthRequired) {
|
|
539
|
+
throw new Error("No re-authentication handler configured. Set onReauthRequired in client config.");
|
|
540
|
+
}
|
|
541
|
+
const lastError = state.lastError || new (await Promise.resolve().then(() => (init_errors(), exports_errors))).AuthenticationError("Manual re-authentication requested", undefined, provider);
|
|
542
|
+
const success = await this.onReauthRequired({
|
|
543
|
+
provider,
|
|
544
|
+
error: lastError
|
|
545
|
+
});
|
|
546
|
+
if (success) {
|
|
547
|
+
this.authState.set(provider, { authenticated: true });
|
|
548
|
+
}
|
|
549
|
+
return success;
|
|
550
|
+
}
|
|
312
551
|
}
|
|
313
552
|
function createMCPClient(config) {
|
|
314
553
|
return new MCPClient(config);
|
|
315
554
|
}
|
|
555
|
+
|
|
556
|
+
// src/index.ts
|
|
557
|
+
init_errors();
|
|
558
|
+
|
|
316
559
|
// src/plugins/github.ts
|
|
317
560
|
var GITHUB_TOOLS = [
|
|
318
561
|
"github_create_issue",
|
|
@@ -457,6 +700,10 @@ function getVercelAITools(client) {
|
|
|
457
700
|
return convertMCPToolsToVercelAI(client);
|
|
458
701
|
}
|
|
459
702
|
export {
|
|
703
|
+
parseServerError,
|
|
704
|
+
isTokenExpiredError,
|
|
705
|
+
isAuthorizationError,
|
|
706
|
+
isAuthError,
|
|
460
707
|
gmailPlugin,
|
|
461
708
|
githubPlugin,
|
|
462
709
|
getVercelAITools,
|
|
@@ -465,7 +712,13 @@ export {
|
|
|
465
712
|
createMCPClient,
|
|
466
713
|
convertMCPToolsToVercelAI,
|
|
467
714
|
convertMCPToolToVercelAI,
|
|
715
|
+
ToolCallError,
|
|
716
|
+
TokenExpiredError,
|
|
468
717
|
MCPMethod,
|
|
469
718
|
MCPClient,
|
|
470
|
-
|
|
719
|
+
IntegrateSDKError,
|
|
720
|
+
HttpSessionTransport,
|
|
721
|
+
ConnectionError,
|
|
722
|
+
AuthorizationError,
|
|
723
|
+
AuthenticationError
|
|
471
724
|
};
|
|
@@ -42,7 +42,7 @@ export declare function convertMCPToolToVercelAI(mcpTool: MCPTool, client: MCPCl
|
|
|
42
42
|
* const tools = convertMCPToolsToVercelAI(mcpClient);
|
|
43
43
|
*
|
|
44
44
|
* const result = await generateText({
|
|
45
|
-
* model: openai('gpt-
|
|
45
|
+
* model: openai('gpt-5'),
|
|
46
46
|
* prompt: 'Create a GitHub issue in my repo',
|
|
47
47
|
* tools,
|
|
48
48
|
* });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-session.d.ts","sourceRoot":"","sources":["../../src/transport/http-session.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAEV,eAAe,EACf,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AAGjC,MAAM,MAAM,cAAc,GAAG,CAC3B,OAAO,EAAE,eAAe,GAAG,mBAAmB,KAC3C,IAAI,CAAC;AAEV,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAAkC;IACzD,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAC,CAAkB;IACxC,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,EAAE,2BAA2B;IAMhD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B;;OAEG;IACG,WAAW,CAAC,CAAC,GAAG,OAAO,EAC3B,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"http-session.d.ts","sourceRoot":"","sources":["../../src/transport/http-session.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAEV,eAAe,EACf,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AAGjC,MAAM,MAAM,cAAc,GAAG,CAC3B,OAAO,EAAE,eAAe,GAAG,mBAAmB,KAC3C,IAAI,CAAC;AAEV,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAAkC;IACzD,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAC,CAAkB;IACxC,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,EAAE,2BAA2B;IAMhD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B;;OAEG;IACG,WAAW,CAAC,CAAC,GAAG,OAAO,EAC3B,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,CAAC,CAAC;IAsFb;;OAEG;YACW,gBAAgB;IAiC9B;;OAEG;YACW,gBAAgB;IAiC9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAiB1B;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,IAAI;IAS9C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAkBjC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,YAAY,IAAI,MAAM,GAAG,SAAS;CAGnC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "integrate-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Type-safe TypeScript SDK for MCP Client with plugin-based OAuth provider configuration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -51,5 +51,4 @@
|
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"typescript": ">=5.0.0"
|
|
53
53
|
}
|
|
54
|
-
}
|
|
55
|
-
|
|
54
|
+
}
|