@seven.io/mcp 1.0.3
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 +295 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +129 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +18 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +88 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +245 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth/flow.d.ts +12 -0
- package/dist/oauth/flow.d.ts.map +1 -0
- package/dist/oauth/flow.js +132 -0
- package/dist/oauth/flow.js.map +1 -0
- package/dist/oauth/pkce.d.ts +17 -0
- package/dist/oauth/pkce.d.ts.map +1 -0
- package/dist/oauth/pkce.js +39 -0
- package/dist/oauth/pkce.js.map +1 -0
- package/dist/oauth/refresh.d.ts +22 -0
- package/dist/oauth/refresh.d.ts.map +1 -0
- package/dist/oauth/refresh.js +53 -0
- package/dist/oauth/refresh.js.map +1 -0
- package/dist/oauth/server.d.ts +18 -0
- package/dist/oauth/server.d.ts.map +1 -0
- package/dist/oauth/server.js +553 -0
- package/dist/oauth/server.js.map +1 -0
- package/dist/oauth/tokens.d.ts +33 -0
- package/dist/oauth/tokens.d.ts.map +1 -0
- package/dist/oauth/tokens.js +104 -0
- package/dist/oauth/tokens.js.map +1 -0
- package/dist/tools/account.d.ts +68 -0
- package/dist/tools/account.d.ts.map +1 -0
- package/dist/tools/account.js +59 -0
- package/dist/tools/account.js.map +1 -0
- package/dist/tools/contacts.d.ts +101 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/contacts.js +111 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/groups.d.ts +65 -0
- package/dist/tools/groups.d.ts.map +1 -0
- package/dist/tools/groups.js +86 -0
- package/dist/tools/groups.js.map +1 -0
- package/dist/tools/lookup.d.ts +22 -0
- package/dist/tools/lookup.d.ts.map +1 -0
- package/dist/tools/lookup.js +88 -0
- package/dist/tools/lookup.js.map +1 -0
- package/dist/tools/numbers.d.ts +79 -0
- package/dist/tools/numbers.d.ts.map +1 -0
- package/dist/tools/numbers.js +106 -0
- package/dist/tools/numbers.js.map +1 -0
- package/dist/tools/rcs.d.ts +100 -0
- package/dist/tools/rcs.d.ts.map +1 -0
- package/dist/tools/rcs.js +86 -0
- package/dist/tools/rcs.js.map +1 -0
- package/dist/tools/sender.d.ts +25 -0
- package/dist/tools/sender.d.ts.map +1 -0
- package/dist/tools/sender.js +25 -0
- package/dist/tools/sender.js.map +1 -0
- package/dist/tools/sms.d.ts +110 -0
- package/dist/tools/sms.d.ts.map +1 -0
- package/dist/tools/sms.js +95 -0
- package/dist/tools/sms.js.map +1 -0
- package/dist/tools/status.d.ts +81 -0
- package/dist/tools/status.d.ts.map +1 -0
- package/dist/tools/status.js +88 -0
- package/dist/tools/status.js.map +1 -0
- package/dist/tools/subaccounts.d.ts +108 -0
- package/dist/tools/subaccounts.d.ts.map +1 -0
- package/dist/tools/subaccounts.js +98 -0
- package/dist/tools/subaccounts.js.map +1 -0
- package/dist/tools/voice.d.ts +57 -0
- package/dist/tools/voice.d.ts.map +1 -0
- package/dist/tools/voice.js +54 -0
- package/dist/tools/voice.js.map +1 -0
- package/dist/tools/webhooks.d.ts +60 -0
- package/dist/tools/webhooks.d.ts.map +1 -0
- package/dist/tools/webhooks.js +58 -0
- package/dist/tools/webhooks.js.map +1 -0
- package/dist/types.d.ts +69 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +49 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { SevenClient } from './client.js';
|
|
6
|
+
import * as fs from 'fs';
|
|
7
|
+
// Import all tool definitions and handlers
|
|
8
|
+
import { rcsTools, sendRCS, deleteRCS, rcsEvents } from './tools/rcs.js';
|
|
9
|
+
import { smsTools, sendSMS, deleteSMS } from './tools/sms.js';
|
|
10
|
+
import { voiceTools, sendVoice, hangupVoice } from './tools/voice.js';
|
|
11
|
+
import { accountTools, getBalance, getPricing, getAnalytics } from './tools/account.js';
|
|
12
|
+
import { lookupTools, lookupFormat, lookupRCS, lookupHLR, lookupMNP, lookupCNAM } from './tools/lookup.js';
|
|
13
|
+
import { statusTools, getStatus, getLogbookSent, getLogbookReceived, getLogbookVoice } from './tools/status.js';
|
|
14
|
+
import { numbersTools, getAvailableNumbers, orderNumber, getActiveNumbers, getNumber, updateNumber, deleteNumber } from './tools/numbers.js';
|
|
15
|
+
import { contactsTools, listContacts, createContact, getContact, updateContact, deleteContact } from './tools/contacts.js';
|
|
16
|
+
import { groupsTools, listGroups, createGroup, getGroup, updateGroup, deleteGroup } from './tools/groups.js';
|
|
17
|
+
import { subaccountsTools, listSubaccounts, createSubaccount, updateSubaccount, transferCredits, deleteSubaccount } from './tools/subaccounts.js';
|
|
18
|
+
import { webhooksTools, listWebhooks, createWebhook, deleteWebhook } from './tools/webhooks.js';
|
|
19
|
+
import { senderTools, validateSender } from './tools/sender.js';
|
|
20
|
+
const API_KEY = process.env.SEVEN_API_KEY;
|
|
21
|
+
const CLIENT_ID = 'seven-mcp'; // Static OAuth client ID
|
|
22
|
+
const LOG_FILE = process.env.SEVEN_LOG_FILE;
|
|
23
|
+
// API key is optional when OAuth is available
|
|
24
|
+
if (!API_KEY && !CLIENT_ID) {
|
|
25
|
+
throw new Error('Authentication configuration error');
|
|
26
|
+
}
|
|
27
|
+
// Debug logging helper - only logs if SEVEN_LOG_FILE is set
|
|
28
|
+
function debugLog(message, data) {
|
|
29
|
+
if (LOG_FILE) {
|
|
30
|
+
const timestamp = new Date().toISOString();
|
|
31
|
+
const logEntry = `[${timestamp}] ${message}${data ? ': ' + JSON.stringify(data) : ''}\n`;
|
|
32
|
+
fs.appendFileSync(LOG_FILE, logEntry);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const client = new SevenClient({
|
|
36
|
+
apiKey: API_KEY,
|
|
37
|
+
clientId: CLIENT_ID
|
|
38
|
+
});
|
|
39
|
+
const server = new Server({
|
|
40
|
+
name: 'mcp-seven',
|
|
41
|
+
version: '1.0.0',
|
|
42
|
+
}, {
|
|
43
|
+
capabilities: {
|
|
44
|
+
tools: {},
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
// Combine all tools
|
|
48
|
+
const allTools = [
|
|
49
|
+
...rcsTools,
|
|
50
|
+
...smsTools,
|
|
51
|
+
...voiceTools,
|
|
52
|
+
...accountTools,
|
|
53
|
+
...lookupTools,
|
|
54
|
+
...statusTools,
|
|
55
|
+
...numbersTools,
|
|
56
|
+
...contactsTools,
|
|
57
|
+
...groupsTools,
|
|
58
|
+
...subaccountsTools,
|
|
59
|
+
...webhooksTools,
|
|
60
|
+
...senderTools,
|
|
61
|
+
];
|
|
62
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
63
|
+
tools: allTools,
|
|
64
|
+
}));
|
|
65
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
66
|
+
try {
|
|
67
|
+
const { name, arguments: args = {} } = request.params;
|
|
68
|
+
// Log incoming request
|
|
69
|
+
debugLog(`Tool request: ${name}`, args);
|
|
70
|
+
let result;
|
|
71
|
+
switch (name) {
|
|
72
|
+
// RCS tools
|
|
73
|
+
case 'send_rcs':
|
|
74
|
+
result = await sendRCS(client, args);
|
|
75
|
+
break;
|
|
76
|
+
case 'delete_rcs':
|
|
77
|
+
result = await deleteRCS(client, args.id);
|
|
78
|
+
break;
|
|
79
|
+
case 'rcs_events':
|
|
80
|
+
result = await rcsEvents(client, args.event_data);
|
|
81
|
+
break;
|
|
82
|
+
// SMS tools
|
|
83
|
+
case 'send_sms':
|
|
84
|
+
result = await sendSMS(client, args);
|
|
85
|
+
break;
|
|
86
|
+
case 'delete_sms':
|
|
87
|
+
result = await deleteSMS(client, args.ids);
|
|
88
|
+
break;
|
|
89
|
+
// Voice tools
|
|
90
|
+
case 'send_voice':
|
|
91
|
+
if (!args.to || !args.text) {
|
|
92
|
+
throw new Error('send_voice requires "to" and "text" parameters');
|
|
93
|
+
}
|
|
94
|
+
result = await sendVoice(client, args);
|
|
95
|
+
break;
|
|
96
|
+
case 'hangup_voice':
|
|
97
|
+
result = await hangupVoice(client, args.call_id);
|
|
98
|
+
break;
|
|
99
|
+
// Account tools
|
|
100
|
+
case 'get_balance':
|
|
101
|
+
result = await getBalance(client);
|
|
102
|
+
break;
|
|
103
|
+
case 'get_pricing':
|
|
104
|
+
result = await getPricing(client, args);
|
|
105
|
+
break;
|
|
106
|
+
case 'get_analytics':
|
|
107
|
+
result = await getAnalytics(client, args);
|
|
108
|
+
break;
|
|
109
|
+
// Lookup tools
|
|
110
|
+
case 'lookup_format':
|
|
111
|
+
result = await lookupFormat(client, args);
|
|
112
|
+
break;
|
|
113
|
+
case 'lookup_rcs':
|
|
114
|
+
result = await lookupRCS(client, args);
|
|
115
|
+
break;
|
|
116
|
+
case 'lookup_hlr':
|
|
117
|
+
result = await lookupHLR(client, args);
|
|
118
|
+
break;
|
|
119
|
+
case 'lookup_mnp':
|
|
120
|
+
result = await lookupMNP(client, args);
|
|
121
|
+
break;
|
|
122
|
+
case 'lookup_cnam':
|
|
123
|
+
result = await lookupCNAM(client, args);
|
|
124
|
+
break;
|
|
125
|
+
// Status & Logbook tools
|
|
126
|
+
case 'get_status':
|
|
127
|
+
result = await getStatus(client, args);
|
|
128
|
+
break;
|
|
129
|
+
case 'get_logbook_sent':
|
|
130
|
+
result = await getLogbookSent(client, args);
|
|
131
|
+
break;
|
|
132
|
+
case 'get_logbook_received':
|
|
133
|
+
result = await getLogbookReceived(client, args);
|
|
134
|
+
break;
|
|
135
|
+
case 'get_logbook_voice':
|
|
136
|
+
result = await getLogbookVoice(client, args);
|
|
137
|
+
break;
|
|
138
|
+
// Numbers tools
|
|
139
|
+
case 'get_available_numbers':
|
|
140
|
+
result = await getAvailableNumbers(client, args);
|
|
141
|
+
break;
|
|
142
|
+
case 'order_number':
|
|
143
|
+
result = await orderNumber(client, args);
|
|
144
|
+
break;
|
|
145
|
+
case 'get_active_numbers':
|
|
146
|
+
result = await getActiveNumbers(client);
|
|
147
|
+
break;
|
|
148
|
+
case 'get_number':
|
|
149
|
+
result = await getNumber(client, args.number);
|
|
150
|
+
break;
|
|
151
|
+
case 'update_number':
|
|
152
|
+
result = await updateNumber(client, args.number, args.config);
|
|
153
|
+
break;
|
|
154
|
+
case 'delete_number':
|
|
155
|
+
result = await deleteNumber(client, args.number);
|
|
156
|
+
break;
|
|
157
|
+
// Contacts tools
|
|
158
|
+
case 'list_contacts':
|
|
159
|
+
result = await listContacts(client);
|
|
160
|
+
break;
|
|
161
|
+
case 'create_contact':
|
|
162
|
+
result = await createContact(client, args);
|
|
163
|
+
break;
|
|
164
|
+
case 'get_contact':
|
|
165
|
+
result = await getContact(client, args.id);
|
|
166
|
+
break;
|
|
167
|
+
case 'update_contact':
|
|
168
|
+
const { id: contactId, ...contactParams } = args;
|
|
169
|
+
result = await updateContact(client, contactId, contactParams);
|
|
170
|
+
break;
|
|
171
|
+
case 'delete_contact':
|
|
172
|
+
result = await deleteContact(client, args.id);
|
|
173
|
+
break;
|
|
174
|
+
// Groups tools
|
|
175
|
+
case 'list_groups':
|
|
176
|
+
result = await listGroups(client);
|
|
177
|
+
break;
|
|
178
|
+
case 'create_group':
|
|
179
|
+
result = await createGroup(client, args);
|
|
180
|
+
break;
|
|
181
|
+
case 'get_group':
|
|
182
|
+
result = await getGroup(client, args.id);
|
|
183
|
+
break;
|
|
184
|
+
case 'update_group':
|
|
185
|
+
const { id: groupId, ...groupParams } = args;
|
|
186
|
+
result = await updateGroup(client, groupId, groupParams);
|
|
187
|
+
break;
|
|
188
|
+
case 'delete_group':
|
|
189
|
+
result = await deleteGroup(client, args.id);
|
|
190
|
+
break;
|
|
191
|
+
// Subaccounts tools
|
|
192
|
+
case 'list_subaccounts':
|
|
193
|
+
result = await listSubaccounts(client);
|
|
194
|
+
break;
|
|
195
|
+
case 'create_subaccount':
|
|
196
|
+
result = await createSubaccount(client, args);
|
|
197
|
+
break;
|
|
198
|
+
case 'update_subaccount':
|
|
199
|
+
result = await updateSubaccount(client, args);
|
|
200
|
+
break;
|
|
201
|
+
case 'transfer_credits':
|
|
202
|
+
result = await transferCredits(client, args);
|
|
203
|
+
break;
|
|
204
|
+
case 'delete_subaccount':
|
|
205
|
+
result = await deleteSubaccount(client, args.id);
|
|
206
|
+
break;
|
|
207
|
+
// Webhooks tools
|
|
208
|
+
case 'list_webhooks':
|
|
209
|
+
result = await listWebhooks(client);
|
|
210
|
+
break;
|
|
211
|
+
case 'create_webhook':
|
|
212
|
+
result = await createWebhook(client, args);
|
|
213
|
+
break;
|
|
214
|
+
case 'delete_webhook':
|
|
215
|
+
result = await deleteWebhook(client, args.id);
|
|
216
|
+
break;
|
|
217
|
+
// Sender tools
|
|
218
|
+
case 'validate_sender':
|
|
219
|
+
result = await validateSender(client, args);
|
|
220
|
+
break;
|
|
221
|
+
default:
|
|
222
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
223
|
+
}
|
|
224
|
+
// Log response and return
|
|
225
|
+
debugLog(`Tool response: ${name}`, result);
|
|
226
|
+
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
debugLog(`Tool error: ${request.params.name}`, { error: error.message });
|
|
230
|
+
return {
|
|
231
|
+
content: [{ type: 'text', text: `Error: ${error.message}` }],
|
|
232
|
+
isError: true,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
async function main() {
|
|
237
|
+
const transport = new StdioServerTransport();
|
|
238
|
+
await server.connect(transport);
|
|
239
|
+
console.error('Seven.io MCP Server running on stdio');
|
|
240
|
+
}
|
|
241
|
+
main().catch((error) => {
|
|
242
|
+
console.error('Fatal error:', error);
|
|
243
|
+
process.exit(1);
|
|
244
|
+
});
|
|
245
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { OAuthTokens } from './tokens.js';
|
|
2
|
+
export interface OAuthConfig {
|
|
3
|
+
clientId: string;
|
|
4
|
+
scope?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Perform complete OAuth 2.0 authorization code flow with PKCE
|
|
8
|
+
* @param config - OAuth configuration
|
|
9
|
+
* @returns OAuth tokens
|
|
10
|
+
*/
|
|
11
|
+
export declare function performOAuthFlow(config: OAuthConfig): Promise<OAuthTokens>;
|
|
12
|
+
//# sourceMappingURL=flow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/oauth/flow.ts"],"names":[],"mappings":"AAKA,OAAO,EAAe,WAAW,EAAE,MAAM,aAAa,CAAC;AAMvD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAiCD;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CA0DhF"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import open from 'open';
|
|
3
|
+
import readline from 'readline';
|
|
4
|
+
import { generateCodeVerifier, generateCodeChallenge, generateState } from './pkce.js';
|
|
5
|
+
import { startCallbackServer, findAvailablePort } from './server.js';
|
|
6
|
+
import { storeTokens } from './tokens.js';
|
|
7
|
+
const AUTHORIZE_ENDPOINT = 'https://oauth.seven.io/authorize';
|
|
8
|
+
const TOKEN_ENDPOINT = 'https://oauth.seven.io/token';
|
|
9
|
+
const ME_ENDPOINT = 'https://oauth.seven.io/me';
|
|
10
|
+
/**
|
|
11
|
+
* Wait for user to press ENTER
|
|
12
|
+
*/
|
|
13
|
+
async function waitForEnter() {
|
|
14
|
+
const rl = readline.createInterface({
|
|
15
|
+
input: process.stdin,
|
|
16
|
+
output: process.stdout
|
|
17
|
+
});
|
|
18
|
+
return new Promise((resolve) => {
|
|
19
|
+
rl.question('Press ENTER to open your browser for authentication...', () => {
|
|
20
|
+
rl.close();
|
|
21
|
+
resolve();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Perform complete OAuth 2.0 authorization code flow with PKCE
|
|
27
|
+
* @param config - OAuth configuration
|
|
28
|
+
* @returns OAuth tokens
|
|
29
|
+
*/
|
|
30
|
+
export async function performOAuthFlow(config) {
|
|
31
|
+
// Generate PKCE parameters
|
|
32
|
+
const codeVerifier = generateCodeVerifier();
|
|
33
|
+
const codeChallenge = generateCodeChallenge(codeVerifier);
|
|
34
|
+
const state = generateState();
|
|
35
|
+
console.log('\n🔐 Starting OAuth authentication flow...');
|
|
36
|
+
// Find an available port from the configured OAuth ports (7177, 9437, 8659)
|
|
37
|
+
const port = await findAvailablePort();
|
|
38
|
+
console.log(`📡 Starting callback server on port ${port}...`);
|
|
39
|
+
// Start the callback server on the available port
|
|
40
|
+
const callbackPromise = startCallbackServer(port, state);
|
|
41
|
+
const redirectUri = `http://127.0.0.1:${port}/callback`;
|
|
42
|
+
// Build authorization URL
|
|
43
|
+
const authUrl = new URL(AUTHORIZE_ENDPOINT);
|
|
44
|
+
authUrl.searchParams.set('response_type', 'code');
|
|
45
|
+
authUrl.searchParams.set('client_id', config.clientId);
|
|
46
|
+
authUrl.searchParams.set('redirect_uri', redirectUri);
|
|
47
|
+
authUrl.searchParams.set('code_challenge', codeChallenge);
|
|
48
|
+
authUrl.searchParams.set('code_challenge_method', 'S256');
|
|
49
|
+
authUrl.searchParams.set('state', state);
|
|
50
|
+
if (config.scope) {
|
|
51
|
+
authUrl.searchParams.set('scope', config.scope);
|
|
52
|
+
}
|
|
53
|
+
// Wait for user confirmation
|
|
54
|
+
await waitForEnter();
|
|
55
|
+
console.log('🌐 Opening browser for authentication...');
|
|
56
|
+
await open(authUrl.toString());
|
|
57
|
+
console.log('⏳ Waiting for authorization (complete login in your browser)...');
|
|
58
|
+
// Wait for callback
|
|
59
|
+
const { code } = await callbackPromise;
|
|
60
|
+
console.log('✅ Authorization received!');
|
|
61
|
+
console.log('🔄 Exchanging authorization code for tokens...');
|
|
62
|
+
// Exchange authorization code for tokens
|
|
63
|
+
const tokens = await exchangeCodeForTokens(config.clientId, code, codeVerifier, redirectUri);
|
|
64
|
+
console.log('👤 Fetching user information...');
|
|
65
|
+
// Fetch user info to get account details
|
|
66
|
+
const userInfo = await fetchUserInfo(tokens.access_token);
|
|
67
|
+
console.log(`✨ Authenticated as: ${userInfo.email || userInfo.user_id}`);
|
|
68
|
+
// Store tokens securely with user-specific account
|
|
69
|
+
await storeTokens(tokens, userInfo.email || userInfo.user_id);
|
|
70
|
+
return tokens;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Fetch user information using the access token
|
|
74
|
+
* @param accessToken - OAuth access token
|
|
75
|
+
* @returns User information
|
|
76
|
+
*/
|
|
77
|
+
async function fetchUserInfo(accessToken) {
|
|
78
|
+
try {
|
|
79
|
+
const response = await axios.get(ME_ENDPOINT, {
|
|
80
|
+
headers: {
|
|
81
|
+
'Authorization': `Bearer ${accessToken}`,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
return response.data;
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
// Return a default user if /me endpoint fails
|
|
88
|
+
return {
|
|
89
|
+
user_id: 'default',
|
|
90
|
+
email: 'oauth-user',
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Exchange authorization code for access token using PKCE
|
|
96
|
+
* @param clientId - OAuth client ID
|
|
97
|
+
* @param code - Authorization code from callback
|
|
98
|
+
* @param codeVerifier - PKCE code verifier
|
|
99
|
+
* @param redirectUri - The redirect URI used in the authorization request
|
|
100
|
+
* @returns OAuth tokens
|
|
101
|
+
*/
|
|
102
|
+
async function exchangeCodeForTokens(clientId, code, codeVerifier, redirectUri) {
|
|
103
|
+
try {
|
|
104
|
+
const params = {
|
|
105
|
+
grant_type: 'authorization_code',
|
|
106
|
+
client_id: clientId,
|
|
107
|
+
code: code,
|
|
108
|
+
redirect_uri: redirectUri,
|
|
109
|
+
code_verifier: codeVerifier,
|
|
110
|
+
};
|
|
111
|
+
const response = await axios.post(TOKEN_ENDPOINT, new URLSearchParams(params).toString(), {
|
|
112
|
+
headers: {
|
|
113
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
const expiresAt = Math.floor(Date.now() / 1000) + response.data.expires_in;
|
|
117
|
+
return {
|
|
118
|
+
access_token: response.data.access_token,
|
|
119
|
+
refresh_token: response.data.refresh_token,
|
|
120
|
+
expires_at: expiresAt,
|
|
121
|
+
token_type: response.data.token_type,
|
|
122
|
+
scope: response.data.scope,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
if (error.response) {
|
|
127
|
+
throw new Error(`Failed to exchange code for tokens: ${error.response.status} - ${JSON.stringify(error.response.data)}`);
|
|
128
|
+
}
|
|
129
|
+
throw new Error(`Failed to exchange code for tokens: ${error.message}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/oauth/flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a cryptographically random code verifier for PKCE
|
|
3
|
+
* @returns Base64URL-encoded random string (43-128 characters)
|
|
4
|
+
*/
|
|
5
|
+
export declare function generateCodeVerifier(): string;
|
|
6
|
+
/**
|
|
7
|
+
* Generate code challenge from code verifier using SHA256
|
|
8
|
+
* @param verifier - The code verifier to hash
|
|
9
|
+
* @returns Base64URL-encoded SHA256 hash of the verifier
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateCodeChallenge(verifier: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Generate a cryptographically random state parameter
|
|
14
|
+
* @returns Random state string for CSRF protection
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateState(): string;
|
|
17
|
+
//# sourceMappingURL=pkce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../../src/oauth/pkce.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAG7C;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG9D;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAGtC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Generate a cryptographically random code verifier for PKCE
|
|
4
|
+
* @returns Base64URL-encoded random string (43-128 characters)
|
|
5
|
+
*/
|
|
6
|
+
export function generateCodeVerifier() {
|
|
7
|
+
const buffer = crypto.randomBytes(32);
|
|
8
|
+
return base64URLEncode(buffer);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Generate code challenge from code verifier using SHA256
|
|
12
|
+
* @param verifier - The code verifier to hash
|
|
13
|
+
* @returns Base64URL-encoded SHA256 hash of the verifier
|
|
14
|
+
*/
|
|
15
|
+
export function generateCodeChallenge(verifier) {
|
|
16
|
+
const hash = crypto.createHash('sha256').update(verifier).digest();
|
|
17
|
+
return base64URLEncode(hash);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Generate a cryptographically random state parameter
|
|
21
|
+
* @returns Random state string for CSRF protection
|
|
22
|
+
*/
|
|
23
|
+
export function generateState() {
|
|
24
|
+
const buffer = crypto.randomBytes(16);
|
|
25
|
+
return base64URLEncode(buffer);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Base64URL encode a buffer (URL-safe base64 without padding)
|
|
29
|
+
* @param buffer - Buffer to encode
|
|
30
|
+
* @returns Base64URL-encoded string
|
|
31
|
+
*/
|
|
32
|
+
function base64URLEncode(buffer) {
|
|
33
|
+
return buffer
|
|
34
|
+
.toString('base64')
|
|
35
|
+
.replace(/\+/g, '-')
|
|
36
|
+
.replace(/\//g, '_')
|
|
37
|
+
.replace(/=/g, '');
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=pkce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/oauth/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACtC,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;IACnE,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACtC,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,MAAc;IACrC,OAAO,MAAM;SACV,QAAQ,CAAC,QAAQ,CAAC;SAClB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { OAuthTokens } from './tokens.js';
|
|
2
|
+
export interface RefreshTokenResponse {
|
|
3
|
+
access_token: string;
|
|
4
|
+
expires_in: number;
|
|
5
|
+
refresh_token: string;
|
|
6
|
+
token_type: string;
|
|
7
|
+
scope?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Refresh OAuth access token using refresh token
|
|
11
|
+
* @param clientId - OAuth client ID
|
|
12
|
+
* @param refreshToken - Current refresh token
|
|
13
|
+
* @returns New OAuth tokens
|
|
14
|
+
*/
|
|
15
|
+
export declare function refreshAccessToken(clientId: string, refreshToken: string): Promise<OAuthTokens>;
|
|
16
|
+
/**
|
|
17
|
+
* Get valid access token, refreshing if necessary
|
|
18
|
+
* @param clientId - OAuth client ID
|
|
19
|
+
* @returns Valid access token
|
|
20
|
+
*/
|
|
21
|
+
export declare function getValidAccessToken(clientId: string): Promise<string>;
|
|
22
|
+
//# sourceMappingURL=refresh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../src/oauth/refresh.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAA0C,MAAM,aAAa,CAAC;AAIlF,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,WAAW,CAAC,CAiCtB;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAa3E"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { storeTokens, getTokens, isTokenExpired } from './tokens.js';
|
|
3
|
+
const TOKEN_ENDPOINT = 'https://oauth.seven.io/token';
|
|
4
|
+
/**
|
|
5
|
+
* Refresh OAuth access token using refresh token
|
|
6
|
+
* @param clientId - OAuth client ID
|
|
7
|
+
* @param refreshToken - Current refresh token
|
|
8
|
+
* @returns New OAuth tokens
|
|
9
|
+
*/
|
|
10
|
+
export async function refreshAccessToken(clientId, refreshToken) {
|
|
11
|
+
try {
|
|
12
|
+
const response = await axios.post(TOKEN_ENDPOINT, new URLSearchParams({
|
|
13
|
+
grant_type: 'refresh_token',
|
|
14
|
+
client_id: clientId,
|
|
15
|
+
refresh_token: refreshToken,
|
|
16
|
+
}).toString(), {
|
|
17
|
+
headers: {
|
|
18
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
const expiresAt = Math.floor(Date.now() / 1000) + response.data.expires_in;
|
|
22
|
+
const newTokens = {
|
|
23
|
+
access_token: response.data.access_token,
|
|
24
|
+
refresh_token: response.data.refresh_token,
|
|
25
|
+
expires_at: expiresAt,
|
|
26
|
+
token_type: response.data.token_type,
|
|
27
|
+
scope: response.data.scope,
|
|
28
|
+
};
|
|
29
|
+
// Store new tokens
|
|
30
|
+
await storeTokens(newTokens);
|
|
31
|
+
return newTokens;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
throw new Error(`Failed to refresh access token: ${error.message}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get valid access token, refreshing if necessary
|
|
39
|
+
* @param clientId - OAuth client ID
|
|
40
|
+
* @returns Valid access token
|
|
41
|
+
*/
|
|
42
|
+
export async function getValidAccessToken(clientId) {
|
|
43
|
+
let tokens = await getTokens();
|
|
44
|
+
if (!tokens) {
|
|
45
|
+
throw new Error('No OAuth tokens found. Please run: npx seven-mcp login');
|
|
46
|
+
}
|
|
47
|
+
// Refresh if expired or expiring soon
|
|
48
|
+
if (isTokenExpired(tokens)) {
|
|
49
|
+
tokens = await refreshAccessToken(clientId, tokens.refresh_token);
|
|
50
|
+
}
|
|
51
|
+
return tokens.access_token;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=refresh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../src/oauth/refresh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAe,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElF,MAAM,cAAc,GAAG,8BAA8B,CAAC;AAUtD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAgB,EAChB,YAAoB;IAEpB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAC/B,cAAc,EACd,IAAI,eAAe,CAAC;YAClB,UAAU,EAAE,eAAe;YAC3B,SAAS,EAAE,QAAQ;YACnB,aAAa,EAAE,YAAY;SAC5B,CAAC,CAAC,QAAQ,EAAE,EACb;YACE,OAAO,EAAE;gBACP,cAAc,EAAE,mCAAmC;aACpD;SACF,CACF,CAAC;QAEF,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC;QAE3E,MAAM,SAAS,GAAgB;YAC7B,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,YAAY;YACxC,aAAa,EAAE,QAAQ,CAAC,IAAI,CAAC,aAAa;YAC1C,UAAU,EAAE,SAAS;YACrB,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,UAAU;YACpC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK;SAC3B,CAAC;QAEF,mBAAmB;QACnB,MAAM,WAAW,CAAC,SAAS,CAAC,CAAC;QAE7B,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,mCAAmC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,QAAgB;IACxD,IAAI,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;IAE/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IAED,sCAAsC;IACtC,IAAI,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,GAAG,MAAM,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IACpE,CAAC;IAED,OAAO,MAAM,CAAC,YAAY,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface CallbackResult {
|
|
2
|
+
code: string;
|
|
3
|
+
state: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const OAUTH_PORTS: number[];
|
|
6
|
+
/**
|
|
7
|
+
* Start a temporary HTTP server to receive OAuth callback
|
|
8
|
+
* @param port - Port to listen on (default: 7177)
|
|
9
|
+
* @param expectedState - Expected state parameter for CSRF protection
|
|
10
|
+
* @returns Promise that resolves with authorization code when callback is received
|
|
11
|
+
*/
|
|
12
|
+
export declare function startCallbackServer(port: number | undefined, expectedState: string): Promise<CallbackResult>;
|
|
13
|
+
/**
|
|
14
|
+
* Find an available port from the OAuth ports list
|
|
15
|
+
* @returns The first available port
|
|
16
|
+
*/
|
|
17
|
+
export declare function findAvailablePort(): Promise<number>;
|
|
18
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/oauth/server.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAID,eAAO,MAAM,WAAW,UAAqB,CAAC;AAE9C;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,YAAO,EACnB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,cAAc,CAAC,CAwgBzB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAwBzD"}
|