mcp4openapi 0.3.0 → 0.3.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/README.md +7 -0
- package/dist/src/auth/oauth-provider.d.ts.map +1 -1
- package/dist/src/auth/oauth-provider.js +5 -2
- package/dist/src/auth/oauth-provider.js.map +1 -1
- package/dist/src/core/cli-config.d.ts.map +1 -1
- package/dist/src/core/cli-config.js +3 -0
- package/dist/src/core/cli-config.js.map +1 -1
- package/dist/src/core/index.d.ts.map +1 -1
- package/dist/src/core/index.js +19 -3
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/generated-schemas.d.ts +45 -0
- package/dist/src/generated-schemas.d.ts.map +1 -1
- package/dist/src/generated-schemas.js +3 -0
- package/dist/src/generated-schemas.js.map +1 -1
- package/dist/src/openapi/openapi-parser.d.ts.map +1 -1
- package/dist/src/openapi/openapi-parser.js +22 -0
- package/dist/src/openapi/openapi-parser.js.map +1 -1
- package/dist/src/profile/profile-allowlist.d.ts +18 -0
- package/dist/src/profile/profile-allowlist.d.ts.map +1 -0
- package/dist/src/profile/profile-allowlist.js +68 -0
- package/dist/src/profile/profile-allowlist.js.map +1 -0
- package/dist/src/profile/profile-loader.d.ts.map +1 -1
- package/dist/src/profile/profile-loader.js +8 -1
- package/dist/src/profile/profile-loader.js.map +1 -1
- package/dist/src/profile/profile-registry.d.ts +7 -1
- package/dist/src/profile/profile-registry.d.ts.map +1 -1
- package/dist/src/profile/profile-registry.js +49 -8
- package/dist/src/profile/profile-registry.js.map +1 -1
- package/dist/src/profile/profile-resolver.d.ts +16 -0
- package/dist/src/profile/profile-resolver.d.ts.map +1 -1
- package/dist/src/profile/profile-resolver.js +120 -0
- package/dist/src/profile/profile-resolver.js.map +1 -1
- package/dist/src/tooling/composite-executor.d.ts.map +1 -1
- package/dist/src/tooling/composite-executor.js +7 -2
- package/dist/src/tooling/composite-executor.js.map +1 -1
- package/dist/src/tooling/proxy-executor.d.ts.map +1 -1
- package/dist/src/tooling/proxy-executor.js +4 -0
- package/dist/src/tooling/proxy-executor.js.map +1 -1
- package/dist/src/tooling/tool-generator.d.ts.map +1 -1
- package/dist/src/tooling/tool-generator.js +36 -3
- package/dist/src/tooling/tool-generator.js.map +1 -1
- package/dist/src/transport/http-transport-config.d.ts.map +1 -1
- package/dist/src/transport/http-transport-config.js +1 -0
- package/dist/src/transport/http-transport-config.js.map +1 -1
- package/dist/src/transport/http-transport.d.ts +5 -0
- package/dist/src/transport/http-transport.d.ts.map +1 -1
- package/dist/src/transport/http-transport.js +63 -1
- package/dist/src/transport/http-transport.js.map +1 -1
- package/dist/src/transport/profile-index.d.ts +84 -0
- package/dist/src/transport/profile-index.d.ts.map +1 -0
- package/dist/src/transport/profile-index.js +405 -0
- package/dist/src/transport/profile-index.js.map +1 -0
- package/dist/src/types/http-transport.d.ts +1 -0
- package/dist/src/types/http-transport.d.ts.map +1 -1
- package/dist/src/types/openapi.d.ts +3 -0
- package/dist/src/types/openapi.d.ts.map +1 -1
- package/dist/src/types/profile.d.ts +3 -0
- package/dist/src/types/profile.d.ts.map +1 -1
- package/dist/src/validation/validation-utils.d.ts.map +1 -1
- package/dist/src/validation/validation-utils.js +1 -0
- package/dist/src/validation/validation-utils.js.map +1 -1
- package/html/profile-index.html +386 -0
- package/package.json +3 -2
- package/profile-schema.json +14 -0
- package/profiles/gitlab/developer-profile-oauth.json +244 -42
- package/profiles/gitlab/developer-profile-oauth.test.json +1009 -5
- package/profiles/gitlab/openapi.yaml +1419 -164
- package/profiles/gitlab/profile-optimized-oauth.json +785 -0
- package/profiles/gitlab/profile-optimized-oauth.test.json +1566 -0
- package/profiles/grafana/openapi.json +28078 -0
- package/profiles/grafana/profile.json +1083 -0
- package/profiles/grafana/profile.test.json +235 -0
- package/profiles/mattermost/openapi.yaml +27434 -0
- package/profiles/mattermost/profile.json +463 -0
- package/profiles/mattermost/profile.test.json +607 -0
- package/profiles/n8n/profile-optimized.json +1002 -364
- package/profiles/n8n/profile-optimized.test.json +43 -43
- package/profiles/n8n/profile.json +1 -1
- package/profiles/n8n-nodes/profile-nodes.json +1 -1
- package/profiles/semgrep/profile.json +1 -1
- package/profiles/youtrack/profile.json +1 -1
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="{{lang}}">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>{{title}}</title>
|
|
7
|
+
<style nonce="{{nonce}}">
|
|
8
|
+
:root {
|
|
9
|
+
color-scheme: light;
|
|
10
|
+
--bg: #f6f2ea;
|
|
11
|
+
--bg-accent: #efe7da;
|
|
12
|
+
--ink: #1f1f1f;
|
|
13
|
+
--muted: #615d56;
|
|
14
|
+
--card: #ffffff;
|
|
15
|
+
--accent: #b15a2b;
|
|
16
|
+
--accent-2: #2b5aa3;
|
|
17
|
+
--border: #e1d8cc;
|
|
18
|
+
--shadow: 0 12px 40px rgba(0, 0, 0, 0.08);
|
|
19
|
+
}
|
|
20
|
+
* { box-sizing: border-box; }
|
|
21
|
+
body {
|
|
22
|
+
margin: 0;
|
|
23
|
+
font-family: "Space Grotesk", "Avenir Next", "Segoe UI", sans-serif;
|
|
24
|
+
color: var(--ink);
|
|
25
|
+
background: radial-gradient(1200px 600px at 10% -20%, #fbe5d6 0%, transparent 60%),
|
|
26
|
+
radial-gradient(800px 600px at 90% 0%, #dbe9ff 0%, transparent 55%),
|
|
27
|
+
var(--bg);
|
|
28
|
+
}
|
|
29
|
+
header {
|
|
30
|
+
padding: 48px 40px 32px;
|
|
31
|
+
}
|
|
32
|
+
h1 {
|
|
33
|
+
font-size: 36px;
|
|
34
|
+
margin: 0 0 8px;
|
|
35
|
+
letter-spacing: -0.02em;
|
|
36
|
+
}
|
|
37
|
+
p {
|
|
38
|
+
margin: 0;
|
|
39
|
+
color: var(--muted);
|
|
40
|
+
line-height: 1.6;
|
|
41
|
+
}
|
|
42
|
+
main {
|
|
43
|
+
display: grid;
|
|
44
|
+
grid-template-columns: minmax(240px, 320px) minmax(0, 1fr);
|
|
45
|
+
gap: 24px;
|
|
46
|
+
padding: 0 40px 48px;
|
|
47
|
+
}
|
|
48
|
+
.panel {
|
|
49
|
+
background: var(--card);
|
|
50
|
+
border-radius: 16px;
|
|
51
|
+
border: 1px solid var(--border);
|
|
52
|
+
box-shadow: var(--shadow);
|
|
53
|
+
padding: 24px;
|
|
54
|
+
}
|
|
55
|
+
.profiles {
|
|
56
|
+
display: flex;
|
|
57
|
+
flex-direction: column;
|
|
58
|
+
gap: 12px;
|
|
59
|
+
}
|
|
60
|
+
.profile-item {
|
|
61
|
+
padding: 12px 14px;
|
|
62
|
+
border-radius: 12px;
|
|
63
|
+
border: 1px solid transparent;
|
|
64
|
+
background: var(--bg-accent);
|
|
65
|
+
cursor: pointer;
|
|
66
|
+
transition: border-color 0.2s ease, transform 0.2s ease;
|
|
67
|
+
}
|
|
68
|
+
.profile-item:hover {
|
|
69
|
+
border-color: var(--accent);
|
|
70
|
+
transform: translateY(-1px);
|
|
71
|
+
}
|
|
72
|
+
.profile-item.active {
|
|
73
|
+
border-color: var(--accent);
|
|
74
|
+
background: #fff5ec;
|
|
75
|
+
}
|
|
76
|
+
.profile-title {
|
|
77
|
+
font-weight: 600;
|
|
78
|
+
margin-bottom: 4px;
|
|
79
|
+
}
|
|
80
|
+
.profile-subtitle {
|
|
81
|
+
font-size: 13px;
|
|
82
|
+
color: var(--muted);
|
|
83
|
+
overflow: hidden;
|
|
84
|
+
text-overflow: ellipsis;
|
|
85
|
+
display: -webkit-box;
|
|
86
|
+
-webkit-line-clamp: 2;
|
|
87
|
+
-webkit-box-orient: vertical;
|
|
88
|
+
}
|
|
89
|
+
.detail-grid {
|
|
90
|
+
display: grid;
|
|
91
|
+
gap: 18px;
|
|
92
|
+
}
|
|
93
|
+
.tab-row {
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-wrap: wrap;
|
|
96
|
+
gap: 8px;
|
|
97
|
+
margin-bottom: 8px;
|
|
98
|
+
}
|
|
99
|
+
.tab {
|
|
100
|
+
border: 1px solid var(--border);
|
|
101
|
+
background: #fff;
|
|
102
|
+
padding: 6px 12px;
|
|
103
|
+
border-radius: 999px;
|
|
104
|
+
cursor: pointer;
|
|
105
|
+
font-size: 13px;
|
|
106
|
+
color: var(--muted);
|
|
107
|
+
}
|
|
108
|
+
.tab.active {
|
|
109
|
+
color: var(--accent);
|
|
110
|
+
border-color: var(--accent);
|
|
111
|
+
background: #fff5ec;
|
|
112
|
+
font-weight: 600;
|
|
113
|
+
}
|
|
114
|
+
.detail-card {
|
|
115
|
+
border: 1px solid var(--border);
|
|
116
|
+
border-radius: 12px;
|
|
117
|
+
padding: 16px;
|
|
118
|
+
background: #fff;
|
|
119
|
+
}
|
|
120
|
+
.detail-card h3 {
|
|
121
|
+
margin: 0 0 8px;
|
|
122
|
+
font-size: 16px;
|
|
123
|
+
}
|
|
124
|
+
.tag-list {
|
|
125
|
+
display: flex;
|
|
126
|
+
flex-wrap: wrap;
|
|
127
|
+
gap: 8px;
|
|
128
|
+
margin-top: 8px;
|
|
129
|
+
}
|
|
130
|
+
.tag {
|
|
131
|
+
background: #f1efe9;
|
|
132
|
+
color: #2d2b28;
|
|
133
|
+
border-radius: 999px;
|
|
134
|
+
padding: 4px 10px;
|
|
135
|
+
font-size: 12px;
|
|
136
|
+
border: 1px solid var(--border);
|
|
137
|
+
}
|
|
138
|
+
code, pre {
|
|
139
|
+
font-family: "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;
|
|
140
|
+
}
|
|
141
|
+
pre {
|
|
142
|
+
background: #0f172a;
|
|
143
|
+
color: #e2e8f0;
|
|
144
|
+
padding: 14px;
|
|
145
|
+
border-radius: 12px;
|
|
146
|
+
overflow-x: auto;
|
|
147
|
+
line-height: 1.6;
|
|
148
|
+
}
|
|
149
|
+
.snippets {
|
|
150
|
+
display: grid;
|
|
151
|
+
gap: 16px;
|
|
152
|
+
}
|
|
153
|
+
.snippet-header {
|
|
154
|
+
display: flex;
|
|
155
|
+
align-items: center;
|
|
156
|
+
justify-content: space-between;
|
|
157
|
+
gap: 12px;
|
|
158
|
+
}
|
|
159
|
+
.snippet-meta {
|
|
160
|
+
display: flex;
|
|
161
|
+
align-items: center;
|
|
162
|
+
gap: 8px;
|
|
163
|
+
}
|
|
164
|
+
.format-pill {
|
|
165
|
+
border: 1px solid var(--border);
|
|
166
|
+
border-radius: 999px;
|
|
167
|
+
padding: 2px 8px;
|
|
168
|
+
font-size: 11px;
|
|
169
|
+
color: var(--muted);
|
|
170
|
+
background: #f7f4ef;
|
|
171
|
+
text-transform: uppercase;
|
|
172
|
+
letter-spacing: 0.05em;
|
|
173
|
+
}
|
|
174
|
+
.copy-btn {
|
|
175
|
+
border: 1px solid var(--border);
|
|
176
|
+
background: #fff;
|
|
177
|
+
color: var(--accent-2);
|
|
178
|
+
border-radius: 999px;
|
|
179
|
+
padding: 6px 12px;
|
|
180
|
+
cursor: pointer;
|
|
181
|
+
font-size: 12px;
|
|
182
|
+
}
|
|
183
|
+
.notice {
|
|
184
|
+
background: #fff8f1;
|
|
185
|
+
border: 1px solid #f6d5bd;
|
|
186
|
+
padding: 12px;
|
|
187
|
+
border-radius: 12px;
|
|
188
|
+
color: #7a3f1e;
|
|
189
|
+
}
|
|
190
|
+
@media (max-width: 960px) {
|
|
191
|
+
main {
|
|
192
|
+
grid-template-columns: 1fr;
|
|
193
|
+
padding: 0 20px 40px;
|
|
194
|
+
}
|
|
195
|
+
header {
|
|
196
|
+
padding: 36px 20px 24px;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
</style>
|
|
200
|
+
</head>
|
|
201
|
+
<body>
|
|
202
|
+
<header>
|
|
203
|
+
<h1>{{title}}</h1>
|
|
204
|
+
<p>{{subtitle}}</p>
|
|
205
|
+
</header>
|
|
206
|
+
<main>
|
|
207
|
+
<section class="panel">
|
|
208
|
+
<div class="profiles" id="profile-list"></div>
|
|
209
|
+
</section>
|
|
210
|
+
<section class="panel">
|
|
211
|
+
<div class="detail-grid" id="profile-detail">
|
|
212
|
+
<noscript>
|
|
213
|
+
<div class="notice">{{noscript}}</div>
|
|
214
|
+
</noscript>
|
|
215
|
+
</div>
|
|
216
|
+
</section>
|
|
217
|
+
</main>
|
|
218
|
+
|
|
219
|
+
<script type="application/json" id="profile-data" nonce="{{nonce}}">{{profile_data}}</script>
|
|
220
|
+
<script type="application/json" id="i18n-data" nonce="{{nonce}}">{{i18n_data}}</script>
|
|
221
|
+
|
|
222
|
+
<script nonce="{{nonce}}">
|
|
223
|
+
const profileData = JSON.parse(document.getElementById('profile-data').textContent || '[]');
|
|
224
|
+
const i18n = JSON.parse(document.getElementById('i18n-data').textContent || '{}');
|
|
225
|
+
|
|
226
|
+
const listEl = document.getElementById('profile-list');
|
|
227
|
+
const detailEl = document.getElementById('profile-detail');
|
|
228
|
+
|
|
229
|
+
function escapeHtml(value) {
|
|
230
|
+
return String(value)
|
|
231
|
+
.replace(/&/g, '&')
|
|
232
|
+
.replace(/</g, '<')
|
|
233
|
+
.replace(/>/g, '>')
|
|
234
|
+
.replace(/"/g, '"')
|
|
235
|
+
.replace(/'/g, ''');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function renderTags(items) {
|
|
239
|
+
if (!items || items.length === 0) {
|
|
240
|
+
return `<div class="profile-subtitle">${escapeHtml(i18n.noEnvVars || '')}</div>`;
|
|
241
|
+
}
|
|
242
|
+
const tags = items.map(item => `<span class="tag">${escapeHtml(item)}</span>`).join('');
|
|
243
|
+
return `<div class="tag-list">${tags}</div>`;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function buildSnippet(template, profile) {
|
|
247
|
+
return template
|
|
248
|
+
.replace(/__PROFILE_ID__/g, profile.profileId)
|
|
249
|
+
.replace(/__PROFILE_NAME__/g, profile.profileName)
|
|
250
|
+
.replace(/__PROFILE_URL__/g, profile.mcpUrl)
|
|
251
|
+
.replace(/__PROFILE_SSE_URL__/g, profile.sseUrl);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function renderSnippets(profile, activeAuth) {
|
|
255
|
+
const blocks = [];
|
|
256
|
+
const order = ['vscode', 'cursor', 'jetbrains', 'claude'];
|
|
257
|
+
const snippets = profile.snippets || {};
|
|
258
|
+
for (const entry of snippets) {
|
|
259
|
+
if (!entry || !entry.key) continue;
|
|
260
|
+
if (activeAuth && entry.authKey && entry.authKey !== activeAuth) continue;
|
|
261
|
+
if (!order.some(prefix => entry.key.startsWith(prefix))) continue;
|
|
262
|
+
const title = entry.label || entry.key;
|
|
263
|
+
const format = entry.format || '';
|
|
264
|
+
const snippet = buildSnippet(entry.content, profile);
|
|
265
|
+
const encodedSnippet = encodeURIComponent(snippet);
|
|
266
|
+
blocks.push(`
|
|
267
|
+
<div class="detail-card">
|
|
268
|
+
<div class="snippet-header">
|
|
269
|
+
<h3>${escapeHtml(title)}</h3>
|
|
270
|
+
<div class="snippet-meta">
|
|
271
|
+
${format ? `<span class="format-pill">${escapeHtml(format)}</span>` : ''}
|
|
272
|
+
<button class="copy-btn" data-copy="${encodedSnippet}">${escapeHtml(i18n.copy || '')}</button>
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
<pre><code>${escapeHtml(snippet)}</code></pre>
|
|
276
|
+
</div>
|
|
277
|
+
`);
|
|
278
|
+
}
|
|
279
|
+
return blocks.join('');
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function buildProfileTitle(profile) {
|
|
283
|
+
const parts = [profile.profileId, profile.profileName, ...(profile.profileAliases || [])];
|
|
284
|
+
const seen = new Set();
|
|
285
|
+
const unique = [];
|
|
286
|
+
for (const part of parts) {
|
|
287
|
+
if (!part) continue;
|
|
288
|
+
const key = String(part);
|
|
289
|
+
if (seen.has(key)) continue;
|
|
290
|
+
seen.add(key);
|
|
291
|
+
unique.push(key);
|
|
292
|
+
}
|
|
293
|
+
if (unique.length === 0) return '';
|
|
294
|
+
if (unique.length === 1) return unique[0];
|
|
295
|
+
return `${unique[0]} (${unique.slice(1).join(', ')})`;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function renderDetail(profile) {
|
|
299
|
+
const title = buildProfileTitle(profile);
|
|
300
|
+
const description = profile.description || i18n.noDescription || '';
|
|
301
|
+
const authTabs = profile.authTabs || [];
|
|
302
|
+
const activeAuth = authTabs.length > 0 ? authTabs[0].key : null;
|
|
303
|
+
detailEl.innerHTML = `
|
|
304
|
+
<div class="detail-card">
|
|
305
|
+
<h3>${escapeHtml(i18n.profileLabel || '')}</h3>
|
|
306
|
+
<div class="profile-title">${escapeHtml(title)}</div>
|
|
307
|
+
<div class="profile-subtitle">${escapeHtml(description)}</div>
|
|
308
|
+
</div>
|
|
309
|
+
<div class="detail-card">
|
|
310
|
+
<h3>${escapeHtml(i18n.endpointLabel || '')}</h3>
|
|
311
|
+
<p><strong>MCP</strong>: ${escapeHtml(profile.mcpUrl)}</p>
|
|
312
|
+
<p><strong>SSE</strong>: ${escapeHtml(profile.sseUrl)}</p>
|
|
313
|
+
</div>
|
|
314
|
+
<div class="detail-card">
|
|
315
|
+
<div class="tab-row" id="auth-tabs">
|
|
316
|
+
${authTabs.map(tab => `
|
|
317
|
+
<button class="tab${tab.key === activeAuth ? ' active' : ''}" data-auth="${escapeHtml(tab.key)}">
|
|
318
|
+
${escapeHtml(tab.label)}
|
|
319
|
+
</button>
|
|
320
|
+
`).join('')}
|
|
321
|
+
</div>
|
|
322
|
+
<div class="snippets" id="snippet-list">
|
|
323
|
+
${renderSnippets(profile, activeAuth)}
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
`;
|
|
327
|
+
|
|
328
|
+
const tabRow = detailEl.querySelector('#auth-tabs');
|
|
329
|
+
const snippetList = detailEl.querySelector('#snippet-list');
|
|
330
|
+
if (tabRow && snippetList) {
|
|
331
|
+
tabRow.addEventListener('click', event => {
|
|
332
|
+
const target = event.target;
|
|
333
|
+
if (!(target instanceof HTMLElement)) return;
|
|
334
|
+
const authKey = target.getAttribute('data-auth');
|
|
335
|
+
if (!authKey) return;
|
|
336
|
+
tabRow.querySelectorAll('.tab').forEach(tab => {
|
|
337
|
+
tab.classList.toggle('active', tab.getAttribute('data-auth') === authKey);
|
|
338
|
+
});
|
|
339
|
+
snippetList.innerHTML = renderSnippets(profile, authKey);
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function renderList(activeId) {
|
|
345
|
+
listEl.innerHTML = '';
|
|
346
|
+
profileData.forEach(profile => {
|
|
347
|
+
const title = buildProfileTitle(profile);
|
|
348
|
+
const item = document.createElement('div');
|
|
349
|
+
item.className = 'profile-item' + (profile.profileId === activeId ? ' active' : '');
|
|
350
|
+
item.innerHTML = `
|
|
351
|
+
<div class="profile-title">${escapeHtml(title)}</div>
|
|
352
|
+
<div class="profile-subtitle">${escapeHtml(profile.description || i18n.noDescription || '')}</div>
|
|
353
|
+
`;
|
|
354
|
+
item.addEventListener('click', () => {
|
|
355
|
+
renderList(profile.profileId);
|
|
356
|
+
renderDetail(profile);
|
|
357
|
+
});
|
|
358
|
+
listEl.appendChild(item);
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (profileData.length > 0) {
|
|
363
|
+
renderList(profileData[0].profileId);
|
|
364
|
+
renderDetail(profileData[0]);
|
|
365
|
+
} else {
|
|
366
|
+
detailEl.innerHTML = `<div class="notice">${escapeHtml(i18n.noProfiles || '')}</div>`;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
document.addEventListener('click', event => {
|
|
370
|
+
const target = event.target;
|
|
371
|
+
if (!(target instanceof HTMLElement)) return;
|
|
372
|
+
if (!target.matches('[data-copy]')) return;
|
|
373
|
+
const text = target.getAttribute('data-copy');
|
|
374
|
+
if (!text) return;
|
|
375
|
+
const decoded = decodeURIComponent(text);
|
|
376
|
+
navigator.clipboard?.writeText(decoded).then(() => {
|
|
377
|
+
target.textContent = i18n.copied || '';
|
|
378
|
+
setTimeout(() => { target.textContent = i18n.copy || ''; }, 1200);
|
|
379
|
+
}).catch(() => {
|
|
380
|
+
target.textContent = i18n.copyFailed || '';
|
|
381
|
+
setTimeout(() => { target.textContent = i18n.copy || ''; }, 1200);
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
</script>
|
|
385
|
+
</body>
|
|
386
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp4openapi",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Universal MCP server that generates tools from any OpenAPI specification",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
15
|
"dist",
|
|
16
|
+
"html",
|
|
16
17
|
"profiles",
|
|
17
18
|
"profile-schema.json",
|
|
18
19
|
"README.md",
|
|
@@ -86,7 +87,7 @@
|
|
|
86
87
|
"supertest": "^7.1.4",
|
|
87
88
|
"ts-to-zod": "^5.0.1",
|
|
88
89
|
"typescript": "^5.9.3",
|
|
89
|
-
"typescript-json-schema": "^0.
|
|
90
|
+
"typescript-json-schema": "^0.67.1",
|
|
90
91
|
"vite": "^6.0.5",
|
|
91
92
|
"vitest": "^3.2.4"
|
|
92
93
|
},
|
package/profile-schema.json
CHANGED
|
@@ -248,6 +248,20 @@
|
|
|
248
248
|
},
|
|
249
249
|
"minItems": 1
|
|
250
250
|
},
|
|
251
|
+
"minLength": {
|
|
252
|
+
"type": "integer",
|
|
253
|
+
"description": "Minimum length for string parameters",
|
|
254
|
+
"minimum": 0
|
|
255
|
+
},
|
|
256
|
+
"maxLength": {
|
|
257
|
+
"type": "integer",
|
|
258
|
+
"description": "Maximum length for string parameters",
|
|
259
|
+
"minimum": 0
|
|
260
|
+
},
|
|
261
|
+
"pattern": {
|
|
262
|
+
"type": "string",
|
|
263
|
+
"description": "Regex pattern for string parameters"
|
|
264
|
+
},
|
|
251
265
|
"items": {
|
|
252
266
|
"type": "object",
|
|
253
267
|
"description": "Item type for array parameters",
|