-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathCreateTokenTool.ts
More file actions
104 lines (90 loc) · 3 KB
/
CreateTokenTool.ts
File metadata and controls
104 lines (90 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js';
import {
CreateTokenSchema,
CreateTokenInput,
SECRET_SCOPES
} from './CreateTokenTool.schema.js';
export class CreateTokenTool extends MapboxApiBasedTool<
typeof CreateTokenSchema
> {
readonly name = 'create_token_tool';
readonly description =
'Create a new Mapbox access token with specified scopes and optional URL restrictions. Token type (public/secret) is automatically determined by scopes: PUBLIC scopes (styles:tiles, styles:read, fonts:read, datasets:read, vision:read) create public tokens; SECRET scopes create secret tokens that are only visible once upon creation.';
constructor() {
super({ inputSchema: CreateTokenSchema });
}
protected async execute(
input: CreateTokenInput,
accessToken?: string
): Promise<{ type: 'text'; text: string }> {
const username = MapboxApiBasedTool.getUserNameFromToken(accessToken);
this.log(
'info',
`CreateTokenTool: Starting token creation with note: "${input.note}", scopes: ${JSON.stringify(input.scopes)}`
);
// Check if any secret scopes are being used
const hasSecretScopes = input.scopes.some((scope) =>
SECRET_SCOPES.includes(scope as (typeof SECRET_SCOPES)[number])
);
if (hasSecretScopes) {
this.log(
'info',
'CreateTokenTool: Creating a SECRET token due to secret scopes. This token will only be visible once upon creation.'
);
} else {
this.log(
'info',
'CreateTokenTool: Creating a PUBLIC token (only public scopes detected).'
);
}
const url = `${MapboxApiBasedTool.MAPBOX_API_ENDPOINT}tokens/v2/${username}?access_token=${accessToken}`;
const body: {
note: string;
scopes: string[];
allowedUrls?: string[];
expires?: string;
} = {
note: input.note,
scopes: input.scopes
};
if (input.allowedUrls) {
if (input.allowedUrls.length > 100) {
throw new Error('Maximum 100 allowed URLs per token');
}
body.allowedUrls = input.allowedUrls;
}
if (input.expires) {
body.expires = input.expires;
}
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
});
if (!response.ok) {
const errorBody = await response.text();
this.log(
'error',
`CreateTokenTool: API Error - Status: ${response.status}, Body: ${errorBody}`
);
throw new Error(
`Failed to create token: ${response.status} ${response.statusText}`
);
}
const data = await response.json();
this.log('info', `CreateTokenTool: Successfully created token`);
return {
type: 'text',
text: JSON.stringify(data, null, 2)
};
} catch (error) {
if (error instanceof Error) {
throw error;
}
throw new Error(`Failed to create token: ${String(error)}`);
}
}
}