mindroot 9.3.0__py3-none-any.whl → 9.6.0__py3-none-any.whl
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.
- mindroot/coreplugins/admin/__init__.py +3 -1
- mindroot/coreplugins/admin/agent_router.py +250 -7
- mindroot/coreplugins/admin/asset_manager.py +164 -0
- mindroot/coreplugins/admin/command_router.py +236 -1
- mindroot/coreplugins/admin/mcp_catalog_routes.py +156 -0
- mindroot/coreplugins/admin/mcp_publish_routes.py +450 -0
- mindroot/coreplugins/admin/mcp_registry_routes.py +495 -0
- mindroot/coreplugins/admin/mcp_routes.py +216 -0
- mindroot/coreplugins/admin/mod.py +62 -0
- mindroot/coreplugins/admin/oauth_callback_router.py +84 -0
- mindroot/coreplugins/admin/persona_handler.py +15 -6
- mindroot/coreplugins/admin/persona_router.py +158 -2
- mindroot/coreplugins/admin/plugin_manager.py +105 -9
- mindroot/coreplugins/admin/plugin_router_fixed.py +23 -0
- mindroot/coreplugins/admin/plugin_router_new_not_working.py +145 -0
- mindroot/coreplugins/admin/plugin_routes.py +114 -0
- mindroot/coreplugins/admin/registry_settings_routes.py +140 -0
- mindroot/coreplugins/admin/router.py +116 -15
- mindroot/coreplugins/admin/service_models.py +1 -1
- mindroot/coreplugins/admin/settings_router.py +1 -0
- mindroot/coreplugins/admin/static/css/admin-custom.css +357 -2
- mindroot/coreplugins/admin/static/css/dark.css +1 -0
- mindroot/coreplugins/admin/static/css/default.css +4 -0
- mindroot/coreplugins/admin/static/js/about-info.js +367 -0
- mindroot/coreplugins/admin/static/js/agent-form.js +83 -3
- mindroot/coreplugins/admin/static/js/api-key-script.js +307 -0
- mindroot/coreplugins/admin/static/js/mcp-manager.js +348 -0
- mindroot/coreplugins/admin/static/js/mcp-publisher.js +780 -0
- mindroot/coreplugins/admin/static/js/persona-editor.js +34 -5
- mindroot/coreplugins/admin/static/js/plugin-toggle.js +1 -1
- mindroot/coreplugins/admin/static/js/recommended-plugin-install.js +63 -0
- mindroot/coreplugins/admin/static/js/registry-auth-section.js +132 -0
- mindroot/coreplugins/admin/static/js/registry-manager-base.js +613 -0
- mindroot/coreplugins/admin/static/js/registry-manager-publish-old-delete.js +166 -0
- mindroot/coreplugins/admin/static/js/registry-manager.js +351 -0
- mindroot/coreplugins/admin/static/js/registry-publish-section.js +377 -0
- mindroot/coreplugins/admin/static/js/registry-search-section.js +400 -0
- mindroot/coreplugins/admin/static/js/registry-search-section.js.bak +3 -0
- mindroot/coreplugins/admin/static/js/registry-settings.js +69 -0
- mindroot/coreplugins/admin/static/js/registry-shared-services.js +903 -0
- mindroot/coreplugins/admin/static/js/registry-simple-sections.js +85 -0
- mindroot/coreplugins/admin/static/js/secure-widget-manager.js +438 -0
- mindroot/coreplugins/admin/static/logo.png +0 -0
- mindroot/coreplugins/admin/templates/admin.jinja2 +275 -110
- mindroot/coreplugins/agent/Assistant/agent.json +27 -11
- mindroot/coreplugins/agent/agent.py +2 -2
- mindroot/coreplugins/agent/command_parser.py +25 -10
- mindroot/coreplugins/agent/templates/system.jinja2 +0 -12
- mindroot/coreplugins/chat/__init__.py +4 -1
- mindroot/coreplugins/chat/router.py +132 -20
- mindroot/coreplugins/chat/router_dedup_patch.py +20 -0
- mindroot/coreplugins/chat/services.py +31 -1
- mindroot/coreplugins/chat/static/css/action-fix.css +32 -0
- mindroot/coreplugins/chat/static/css/admin-custom.css +5 -3
- mindroot/coreplugins/chat/static/css/dark.css +24 -3
- mindroot/coreplugins/chat/static/css/default.css +24 -3
- mindroot/coreplugins/chat/static/css/main.css +1 -0
- mindroot/coreplugins/chat/static/js/action.js +137 -60
- mindroot/coreplugins/chat/static/js/chat-history.js +3 -0
- mindroot/coreplugins/chat/static/js/chat.js +59 -16
- mindroot/coreplugins/chat/static/js/chat.js.diff +221 -0
- mindroot/coreplugins/chat/static/js/chatform.js +2 -2
- mindroot/coreplugins/chat/static/site.webmanifest +1 -1
- mindroot/coreplugins/chat/templates/chat.jinja2 +3 -3
- mindroot/coreplugins/chat/widget_manager.py +139 -0
- mindroot/coreplugins/chat/widget_routes.py +287 -0
- mindroot/coreplugins/check_list/inject/admin.jinja2 +1 -1
- mindroot/coreplugins/email/__init__.py +2 -0
- mindroot/coreplugins/email/email_provider.py +2 -2
- mindroot/coreplugins/email/mod.py +100 -0
- mindroot/coreplugins/email/services.py +5 -3
- mindroot/coreplugins/email/smtp_handler.py +9 -3
- mindroot/coreplugins/email/test_email_service.py +75 -0
- mindroot/coreplugins/env_manager/mod.py +61 -25
- mindroot/coreplugins/home/router.py +37 -2
- mindroot/coreplugins/home/static/imgs/logo.png +0 -0
- mindroot/coreplugins/home/static/imgs/logo.png.bak +0 -0
- mindroot/coreplugins/home/static/imgs/logo_teal.png +0 -0
- mindroot/coreplugins/home/static/imgs/logo_teal2.png +0 -0
- mindroot/coreplugins/home/static/imgs/logo_teal_detailed.png +0 -0
- mindroot/coreplugins/home/static/imgs/logo_teal_python.png +0 -0
- mindroot/coreplugins/home/templates/home.jinja2 +15 -6
- mindroot/coreplugins/index/indices/default/index.json +39 -6
- mindroot/coreplugins/jwt_auth/middleware.py +47 -2
- mindroot/coreplugins/jwt_auth/mod.py +40 -17
- mindroot/coreplugins/l8n/__init__.py +6 -0
- mindroot/coreplugins/l8n/debug_loader.py +85 -0
- mindroot/coreplugins/l8n/debug_middleware.py +74 -0
- mindroot/coreplugins/l8n/l8n_constants.py +19 -0
- mindroot/coreplugins/l8n/language_detection.py +183 -0
- mindroot/coreplugins/l8n/middleware.py +151 -0
- mindroot/coreplugins/l8n/mod.py +277 -0
- mindroot/coreplugins/l8n/monkey_patch_to_delete.py +186 -0
- mindroot/coreplugins/l8n/test_enhanced.py +298 -0
- mindroot/coreplugins/l8n/test_l8n.py +95 -0
- mindroot/coreplugins/l8n/test_l8n_standalone.py +251 -0
- mindroot/coreplugins/l8n/test_middleware.py +272 -0
- mindroot/coreplugins/l8n/utils.py +232 -0
- mindroot/coreplugins/mcp_/__init__.py +14 -0
- mindroot/coreplugins/mcp_/catalog_commands.py +328 -0
- mindroot/coreplugins/mcp_/catalog_manager.py +263 -0
- mindroot/coreplugins/mcp_/dynamic_commands.py +154 -0
- mindroot/coreplugins/mcp_/mcp_manager.py +1031 -0
- mindroot/coreplugins/mcp_/mod.py +367 -0
- mindroot/coreplugins/mcp_/oauth_storage.py +144 -0
- mindroot/coreplugins/mcp_/server_installer.py +79 -0
- mindroot/coreplugins/mcp_/setup.py +26 -0
- mindroot/coreplugins/mcp_/test_dynamic_commands.py +134 -0
- mindroot/coreplugins/mcp_/testmcpclient.py +92 -0
- mindroot/coreplugins/persona/mod.py +12 -7
- mindroot/coreplugins/signup/templates/signup.jinja2 +1 -1
- mindroot/coreplugins/subscriptions/__init__.py +1 -0
- mindroot/coreplugins/subscriptions/mod.py +14 -3
- mindroot/coreplugins/subscriptions/router.py +3 -0
- mindroot/coreplugins/user_service/__init__.py +1 -2
- mindroot/coreplugins/user_service/admin_init.py +1 -0
- mindroot/coreplugins/user_service/email_service.py +72 -17
- mindroot/coreplugins/user_service/mod.py +10 -2
- mindroot/coreplugins/user_service/router.py +2 -0
- mindroot/lib/auth/api_key.py +28 -0
- mindroot/lib/cli/plugins.py +94 -0
- mindroot/lib/plugins/default_plugin_manifest.json +20 -0
- mindroot/lib/plugins/installation.py +5 -5
- mindroot/lib/plugins/l8n_static_handler.py +225 -0
- mindroot/lib/plugins/loader.py +33 -3
- mindroot/lib/plugins/loader_with_l8n.py +281 -0
- mindroot/lib/plugins/manifest.py +236 -24
- mindroot/lib/providers/commands.py +3 -1
- mindroot/lib/route_decorators.py +5 -5
- mindroot/lib/templates.py +183 -11
- mindroot/lib/utils/merge_arrays.py +1 -1
- mindroot/migrate.py +39 -20
- mindroot/registry/data_access.py +1 -1
- mindroot/server.py +42 -13
- mindroot/server_missing_normal_args.py +197 -0
- mindroot/server_prev.py +173 -0
- {mindroot-9.3.0.dist-info → mindroot-9.6.0.dist-info}/METADATA +7 -2
- {mindroot-9.3.0.dist-info → mindroot-9.6.0.dist-info}/RECORD +143 -113
- mindroot/coreplugins/admin/plugin_manager_backup.py +0 -615
- mindroot/coreplugins/admin/static/favicon/about.txt +0 -6
- mindroot/coreplugins/admin/static/favicon/android-chrome-512x512.png +0 -0
- mindroot/coreplugins/admin/static/favicon/apple-touch-icon.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon-16x16.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon-32x32.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon.ico +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/about.txt +0 -6
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/android-chrome-192x192.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/android-chrome-512x512.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/apple-touch-icon.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon-16x16.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon-32x32.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon.ico +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/site.webmanifest +0 -1
- mindroot/coreplugins/admin/static/favicon/logo.png +0 -0
- mindroot/coreplugins/admin/static/favicon/site.webmanifest +0 -1
- mindroot/coreplugins/admin/static/js/backup/agent-editor.js +0 -186
- mindroot/coreplugins/admin/static/js/backup/agent-form.js +0 -1133
- mindroot/coreplugins/admin/static/js/backup/agent-list.js +0 -94
- mindroot/coreplugins/chat/static/favicon/about.txt +0 -6
- mindroot/coreplugins/chat/static/favicon/android-chrome-192x192.png +0 -0
- mindroot/coreplugins/chat/static/favicon/android-chrome-512x512.png +0 -0
- mindroot/coreplugins/chat/static/favicon/apple-touch-icon.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon-16x16.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon-32x32.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon.ico +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/about.txt +0 -6
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/android-chrome-192x192.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/android-chrome-512x512.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/apple-touch-icon.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon-16x16.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon-32x32.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon.ico +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/site.webmanifest +0 -1
- mindroot/coreplugins/chat/static/favicon/logo.png +0 -0
- mindroot/coreplugins/chat/static/favicon/site.webmanifest +0 -1
- mindroot/coreplugins/index/default.json +0 -76
- mindroot/coreplugins/user_service/file_trigger_service.py +0 -12
- mindroot/coreplugins/user_service/hooks.py +0 -23
- /mindroot/coreplugins/{admin/static/favicon/android-chrome-192x192.png → home/static/imgs/backuplogo.png} +0 -0
- {mindroot-9.3.0.dist-info → mindroot-9.6.0.dist-info}/WHEEL +0 -0
- {mindroot-9.3.0.dist-info → mindroot-9.6.0.dist-info}/entry_points.txt +0 -0
- {mindroot-9.3.0.dist-info → mindroot-9.6.0.dist-info}/licenses/LICENSE +0 -0
- {mindroot-9.3.0.dist-info → mindroot-9.6.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,780 @@
|
|
|
1
|
+
import { BaseEl } from '/admin/static/js/base.js';
|
|
2
|
+
import { html, css } from '/admin/static/js/lit-core.min.js';
|
|
3
|
+
|
|
4
|
+
class McpPublisher extends BaseEl {
|
|
5
|
+
static properties = {
|
|
6
|
+
serverType: { type: String },
|
|
7
|
+
serverName: { type: String },
|
|
8
|
+
serverDescription: { type: String },
|
|
9
|
+
localConfig: { type: Object },
|
|
10
|
+
remoteUrl: { type: String },
|
|
11
|
+
authType: { type: String },
|
|
12
|
+
discoveredTools: { type: Array },
|
|
13
|
+
loading: { type: Boolean },
|
|
14
|
+
error: { type: String },
|
|
15
|
+
success: { type: String },
|
|
16
|
+
oauthFlow: { type: Object },
|
|
17
|
+
oauthWindow: { type: Object },
|
|
18
|
+
registryUrl: { type: String },
|
|
19
|
+
authToken: { type: String },
|
|
20
|
+
isLoggedIn: { type: Boolean },
|
|
21
|
+
requiredPlaceholders: { type: Array },
|
|
22
|
+
placeholderValues: { type: Object }
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
static styles = css`
|
|
26
|
+
:host {
|
|
27
|
+
display: block;
|
|
28
|
+
width: 100%;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.mcp-publisher {
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
gap: 1rem;
|
|
35
|
+
max-width: 800px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.section {
|
|
39
|
+
background: rgb(10, 10, 25);
|
|
40
|
+
border-radius: 8px;
|
|
41
|
+
padding: 1rem;
|
|
42
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.form-group {
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-direction: column;
|
|
48
|
+
gap: 0.5rem;
|
|
49
|
+
margin-bottom: 1rem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.form-row {
|
|
53
|
+
display: flex;
|
|
54
|
+
gap: 1rem;
|
|
55
|
+
align-items: center;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
label {
|
|
59
|
+
color: #fff;
|
|
60
|
+
font-weight: 500;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
input, textarea, select {
|
|
64
|
+
background: #2a2a40;
|
|
65
|
+
color: #fff;
|
|
66
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
67
|
+
padding: 0.5rem;
|
|
68
|
+
border-radius: 4px;
|
|
69
|
+
font-family: inherit;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
input:focus, textarea:focus, select:focus {
|
|
73
|
+
outline: none;
|
|
74
|
+
border-color: #4a9eff;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
textarea {
|
|
78
|
+
min-height: 100px;
|
|
79
|
+
font-family: 'Courier New', monospace;
|
|
80
|
+
resize: vertical;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.checkbox-group {
|
|
84
|
+
display: flex;
|
|
85
|
+
gap: 1rem;
|
|
86
|
+
margin: 1rem 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.checkbox-item {
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
gap: 0.5rem;
|
|
93
|
+
cursor: pointer;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
input[type="checkbox"] {
|
|
97
|
+
width: auto;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
button {
|
|
101
|
+
background: #2a2a40;
|
|
102
|
+
color: #fff;
|
|
103
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
104
|
+
padding: 0.5rem 1rem;
|
|
105
|
+
border-radius: 4px;
|
|
106
|
+
cursor: pointer;
|
|
107
|
+
transition: background 0.2s;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
button:hover {
|
|
111
|
+
background: #3a3a50;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
button.primary {
|
|
115
|
+
background: #4a9eff;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
button.primary:hover {
|
|
119
|
+
background: #3a8eef;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
button:disabled {
|
|
123
|
+
opacity: 0.5;
|
|
124
|
+
cursor: not-allowed;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.tools-preview {
|
|
128
|
+
background: rgba(0, 0, 0, 0.2);
|
|
129
|
+
border-radius: 4px;
|
|
130
|
+
padding: 1rem;
|
|
131
|
+
margin-top: 1rem;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.tool-item {
|
|
135
|
+
background: rgba(255, 255, 255, 0.05);
|
|
136
|
+
padding: 0.5rem;
|
|
137
|
+
border-radius: 4px;
|
|
138
|
+
margin-bottom: 0.5rem;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.tool-name {
|
|
142
|
+
font-weight: bold;
|
|
143
|
+
color: #4a9eff;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.tool-description {
|
|
147
|
+
color: #ccc;
|
|
148
|
+
font-size: 0.9rem;
|
|
149
|
+
margin-top: 0.25rem;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.error {
|
|
153
|
+
background: rgba(220, 53, 69, 0.2);
|
|
154
|
+
color: #dc3545;
|
|
155
|
+
padding: 0.5rem;
|
|
156
|
+
border-radius: 4px;
|
|
157
|
+
margin: 0.5rem 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.success {
|
|
161
|
+
background: rgba(40, 167, 69, 0.2);
|
|
162
|
+
color: #28a745;
|
|
163
|
+
padding: 0.5rem;
|
|
164
|
+
border-radius: 4px;
|
|
165
|
+
margin: 0.5rem 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.loading {
|
|
169
|
+
text-align: center;
|
|
170
|
+
color: #ccc;
|
|
171
|
+
padding: 1rem;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.help-text {
|
|
175
|
+
font-size: 0.8rem;
|
|
176
|
+
color: #999;
|
|
177
|
+
margin-top: 0.25rem;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.json-example {
|
|
181
|
+
background: rgba(0, 0, 0, 0.3);
|
|
182
|
+
padding: 0.5rem;
|
|
183
|
+
border-radius: 4px;
|
|
184
|
+
font-family: 'Courier New', monospace;
|
|
185
|
+
font-size: 0.8rem;
|
|
186
|
+
color: #ccc;
|
|
187
|
+
white-space: pre-wrap;
|
|
188
|
+
margin-top: 0.5rem;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.oauth-status {
|
|
192
|
+
background: rgba(74, 158, 255, 0.2);
|
|
193
|
+
color: #4a9eff;
|
|
194
|
+
padding: 0.5rem;
|
|
195
|
+
border-radius: 4px;
|
|
196
|
+
margin: 0.5rem 0;
|
|
197
|
+
}
|
|
198
|
+
`;
|
|
199
|
+
|
|
200
|
+
constructor() {
|
|
201
|
+
super();
|
|
202
|
+
this.serverType = 'local';
|
|
203
|
+
this.serverName = '';
|
|
204
|
+
this.serverDescription = '';
|
|
205
|
+
this.localConfig = {
|
|
206
|
+
command: '',
|
|
207
|
+
args: [],
|
|
208
|
+
env: {}
|
|
209
|
+
};
|
|
210
|
+
this.remoteUrl = '';
|
|
211
|
+
this.authType = 'none';
|
|
212
|
+
this.discoveredTools = [];
|
|
213
|
+
this.loading = false;
|
|
214
|
+
this.error = '';
|
|
215
|
+
this.success = '';
|
|
216
|
+
this.oauthFlow = null;
|
|
217
|
+
this.oauthWindow = null;
|
|
218
|
+
this.registryUrl = '';
|
|
219
|
+
this.authToken = '';
|
|
220
|
+
this.isLoggedIn = false;
|
|
221
|
+
this.requiredPlaceholders = [];
|
|
222
|
+
this.placeholderValues = {};
|
|
223
|
+
|
|
224
|
+
// Listen for OAuth callback messages
|
|
225
|
+
window.addEventListener('message', this.handleOAuthCallback.bind(this));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
disconnectedCallback() {
|
|
229
|
+
super.disconnectedCallback();
|
|
230
|
+
// Clean up OAuth window if it exists
|
|
231
|
+
if (this.oauthWindow && !this.oauthWindow.closed) {
|
|
232
|
+
this.oauthWindow.close();
|
|
233
|
+
}
|
|
234
|
+
// Remove event listener
|
|
235
|
+
window.removeEventListener('message', this.handleOAuthCallback.bind(this));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
handleServerTypeChange(e) {
|
|
239
|
+
this.serverType = e.target.value;
|
|
240
|
+
this.discoveredTools = [];
|
|
241
|
+
this.error = '';
|
|
242
|
+
this.oauthFlow = null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
handleLocalConfigChange(e) {
|
|
246
|
+
try {
|
|
247
|
+
const config = JSON.parse(e.target.value);
|
|
248
|
+
this.localConfig = {
|
|
249
|
+
command: config.command || '',
|
|
250
|
+
args: config.args || [],
|
|
251
|
+
env: config.env || {}
|
|
252
|
+
};
|
|
253
|
+
this.scanForRequiredSecrets();
|
|
254
|
+
this.error = '';
|
|
255
|
+
} catch (error) {
|
|
256
|
+
this.error = 'Invalid JSON configuration';
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
scanForRequiredSecrets() {
|
|
261
|
+
const placeholders = new Set();
|
|
262
|
+
|
|
263
|
+
// 1. Add all keys from the 'env' object automatically.
|
|
264
|
+
if (this.localConfig.env) {
|
|
265
|
+
Object.keys(this.localConfig.env).forEach(key => placeholders.add(key));
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// 2. Scan the entire configuration for <PLACEHOLDER> syntax.
|
|
269
|
+
const configString = JSON.stringify(this.localConfig);
|
|
270
|
+
const placeholderRegex = /<([A-Z0-9_]+)>/g;
|
|
271
|
+
let match;
|
|
272
|
+
while ((match = placeholderRegex.exec(configString)) !== null) {
|
|
273
|
+
placeholders.add(match[1]);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
this.requiredPlaceholders = Array.from(placeholders);
|
|
277
|
+
// Reset values for placeholders that no longer exist
|
|
278
|
+
const newValues = {};
|
|
279
|
+
this.requiredPlaceholders.forEach(p => {
|
|
280
|
+
if (this.placeholderValues[p]) {
|
|
281
|
+
newValues[p] = this.placeholderValues[p];
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
this.placeholderValues = newValues;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async discoverTools() {
|
|
288
|
+
if (!this.serverName.trim()) {
|
|
289
|
+
this.error = 'Please enter a server name first';
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
this.loading = true;
|
|
294
|
+
this.error = '';
|
|
295
|
+
this.success = '';
|
|
296
|
+
this.discoveredTools = [];
|
|
297
|
+
this.oauthFlow = null;
|
|
298
|
+
|
|
299
|
+
try {
|
|
300
|
+
if (this.serverType === 'local') {
|
|
301
|
+
await this.discoverLocalTools();
|
|
302
|
+
} else {
|
|
303
|
+
await this.discoverRemoteTools();
|
|
304
|
+
}
|
|
305
|
+
} catch (error) {
|
|
306
|
+
this.error = `Failed to discover tools: ${error.message}`;
|
|
307
|
+
} finally {
|
|
308
|
+
this.loading = false;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
async discoverLocalTools() {
|
|
313
|
+
if (!this.localConfig.command) {
|
|
314
|
+
throw new Error('Command is required for local servers');
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Use the new dedicated endpoint for testing local servers
|
|
318
|
+
const response = await fetch('/admin/mcp/test-local', {
|
|
319
|
+
method: 'POST',
|
|
320
|
+
headers: { 'Content-Type': 'application/json' },
|
|
321
|
+
body: JSON.stringify({
|
|
322
|
+
name: this.serverName,
|
|
323
|
+
command: this.localConfig.command,
|
|
324
|
+
args: this.localConfig.args,
|
|
325
|
+
env: this.localConfig.env,
|
|
326
|
+
secrets: this.placeholderValues
|
|
327
|
+
})
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
const data = await response.json();
|
|
331
|
+
if (data.success) {
|
|
332
|
+
this.discoveredTools = data.tools || [];
|
|
333
|
+
this.success = data.message;
|
|
334
|
+
} else {
|
|
335
|
+
throw new Error(data.detail || 'Local server test failed');
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
async discoverRemoteTools() {
|
|
340
|
+
if (!this.remoteUrl) {
|
|
341
|
+
throw new Error('URL is required for remote servers');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Use the new backend endpoint that handles OAuth
|
|
345
|
+
console.log('[MCP-Publisher] discoverRemoteTools: starting test-remote', { url: this.remoteUrl, name: this.serverName });
|
|
346
|
+
const response = await fetch('/admin/mcp/test-remote', {
|
|
347
|
+
method: 'POST',
|
|
348
|
+
headers: { 'Content-Type': 'application/json' },
|
|
349
|
+
body: JSON.stringify({
|
|
350
|
+
url: this.remoteUrl,
|
|
351
|
+
name: this.serverName
|
|
352
|
+
})
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
const data = await response.json();
|
|
356
|
+
console.log('[MCP-Publisher] discoverRemoteTools: response', data);
|
|
357
|
+
|
|
358
|
+
if (data.success) {
|
|
359
|
+
// Successfully connected without OAuth
|
|
360
|
+
this.discoveredTools = data.tools || [];
|
|
361
|
+
console.log('[MCP-Publisher] discoverRemoteTools: tools discovered (no OAuth)', this.discoveredTools);
|
|
362
|
+
this.success = data.message;
|
|
363
|
+
// Default remote auth type to 'auto' unless specified
|
|
364
|
+
this.authType = 'auto';
|
|
365
|
+
} else if (data.requires_oauth) {
|
|
366
|
+
// OAuth flow required
|
|
367
|
+
this.oauthFlow = {
|
|
368
|
+
auth_url: data.auth_url,
|
|
369
|
+
flow_id: data.flow_id,
|
|
370
|
+
server_name: data.server_name
|
|
371
|
+
};
|
|
372
|
+
// Ensure we publish with remote auth type when OAuth was needed
|
|
373
|
+
this.authType = 'oauth2';
|
|
374
|
+
this.success = data.message;
|
|
375
|
+
console.log('[MCP-Publisher] discoverRemoteTools: OAuth required', this.oauthFlow);
|
|
376
|
+
|
|
377
|
+
// Automatically open OAuth window
|
|
378
|
+
await this.startOAuthFlow();
|
|
379
|
+
} else {
|
|
380
|
+
// Other error
|
|
381
|
+
throw new Error(data.detail || 'Connection failed');
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
async startOAuthFlow() {
|
|
386
|
+
if (!this.oauthFlow || !this.oauthFlow.auth_url) {
|
|
387
|
+
this.error = 'No OAuth flow available';
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
this.success = 'Opening OAuth authorization window...';
|
|
392
|
+
console.log('[MCP-Publisher] startOAuthFlow: opening', this.oauthFlow?.auth_url);
|
|
393
|
+
|
|
394
|
+
// Open OAuth window
|
|
395
|
+
const width = 600;
|
|
396
|
+
const height = 700;
|
|
397
|
+
const left = (screen.width - width) / 2;
|
|
398
|
+
const top = (screen.height - height) / 2;
|
|
399
|
+
|
|
400
|
+
this.oauthWindow = window.open(
|
|
401
|
+
this.oauthFlow.auth_url,
|
|
402
|
+
'oauth_window',
|
|
403
|
+
`width=${width},height=${height},left=${left},top=${top},scrollbars=yes,resizable=yes`
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
if (!this.oauthWindow) {
|
|
407
|
+
this.error = 'Failed to open OAuth window. Please allow popups and try again.';
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Monitor window closure
|
|
412
|
+
const checkClosed = setInterval(() => {
|
|
413
|
+
// Polling for window status; discoveredTools length:', this.discoveredTools?.length
|
|
414
|
+
console.log('[MCP-Publisher] startOAuthFlow: polling window closed?', this.oauthWindow?.closed, 'tools:', this.discoveredTools?.length);
|
|
415
|
+
if (this.oauthWindow && this.oauthWindow.closed) {
|
|
416
|
+
clearInterval(checkClosed);
|
|
417
|
+
if (!this.discoveredTools.length) {
|
|
418
|
+
this.error = 'OAuth window was closed before completion';
|
|
419
|
+
this.loading = false;
|
|
420
|
+
}
|
|
421
|
+
} else {
|
|
422
|
+
if (!this.oauthWindow && this.discoveredTools.length) {
|
|
423
|
+
clearInterval(checkClosed);
|
|
424
|
+
this.success = 'OAuth flow completed successfully, tools discovered.';
|
|
425
|
+
this.loading = false;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}, 1000);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
async handleOAuthCallback(event) {
|
|
432
|
+
// Only handle messages from our OAuth window
|
|
433
|
+
if (!this.oauthWindow || event.source !== this.oauthWindow) {
|
|
434
|
+
// Note: admin UI can receive unrelated messages; ignore safely
|
|
435
|
+
// console.debug('[MCP-Publisher] handleOAuthCallback: ignoring message from different source');
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (event.data && event.data.type === 'oauth_callback' && event.data.code) {
|
|
440
|
+
try {
|
|
441
|
+
this.success = 'OAuth authorization received, completing flow...';
|
|
442
|
+
console.log('[MCP-Publisher] handleOAuthCallback: received code/state', { code: !!event.data.code, state: event.data.state });
|
|
443
|
+
|
|
444
|
+
// Close the OAuth window
|
|
445
|
+
this.oauthWindow.close();
|
|
446
|
+
this.oauthWindow = null;
|
|
447
|
+
|
|
448
|
+
// Complete the OAuth flow
|
|
449
|
+
const response = await fetch('/admin/mcp/complete-oauth', {
|
|
450
|
+
method: 'POST',
|
|
451
|
+
headers: { 'Content-Type': 'application/json' },
|
|
452
|
+
body: JSON.stringify({
|
|
453
|
+
server_name: this.oauthFlow.server_name,
|
|
454
|
+
code: event.data.code,
|
|
455
|
+
state: event.data.state
|
|
456
|
+
})
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
const data = await response.json();
|
|
460
|
+
console.log('[MCP-Publisher] handleOAuthCallback: complete-oauth response', data);
|
|
461
|
+
|
|
462
|
+
if (data.success) {
|
|
463
|
+
// Prefer tools from response; if pending, poll once for updated status
|
|
464
|
+
if (Array.isArray(data.tools) && data.tools.length) {
|
|
465
|
+
this.discoveredTools = data.tools;
|
|
466
|
+
console.log('[MCP-Publisher] handleOAuthCallback: tools from complete-oauth', this.discoveredTools);
|
|
467
|
+
} else {
|
|
468
|
+
// Fallback: ask backend for oauth-status and try to extract tools if connected
|
|
469
|
+
try {
|
|
470
|
+
const statusResp = await fetch(`/admin/mcp/oauth-status/${this.oauthFlow.server_name}`);
|
|
471
|
+
if (statusResp.ok) {
|
|
472
|
+
const statusData = await statusResp.json();
|
|
473
|
+
console.log('[MCP-Publisher] handleOAuthCallback: oauth-status', statusData);
|
|
474
|
+
// If server appears connected, re-trigger a lightweight test to fetch tools
|
|
475
|
+
if (statusData && statusData.status === 'connected') {
|
|
476
|
+
const recheck = await fetch('/admin/mcp/test-remote', {
|
|
477
|
+
method: 'POST',
|
|
478
|
+
headers: { 'Content-Type': 'application/json' },
|
|
479
|
+
body: JSON.stringify({ url: this.remoteUrl, name: this.oauthFlow.server_name })
|
|
480
|
+
});
|
|
481
|
+
const reData = await recheck.json();
|
|
482
|
+
console.log('[MCP-Publisher] handleOAuthCallback: recheck test-remote response', reData);
|
|
483
|
+
if (reData.success && Array.isArray(reData.tools)) {
|
|
484
|
+
this.discoveredTools = reData.tools;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
// If still pending, start a short polling loop for connection then fetch tools
|
|
488
|
+
if (!this.discoveredTools.length) {
|
|
489
|
+
await this.pollForToolsAfterOAuth(6);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
} catch (e) {
|
|
493
|
+
console.warn('Post-OAuth tool recheck failed', e);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
this.success = data.message;
|
|
497
|
+
this.oauthFlow = null;
|
|
498
|
+
} else {
|
|
499
|
+
throw new Error(data.detail || 'OAuth completion failed');
|
|
500
|
+
}
|
|
501
|
+
} catch (error) {
|
|
502
|
+
this.error = `OAuth completion failed: ${error.message}`;
|
|
503
|
+
this.oauthFlow = null;
|
|
504
|
+
} finally {
|
|
505
|
+
this.loading = false;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
async pollForToolsAfterOAuth(maxTries = 6, delayMs = 1000) {
|
|
511
|
+
console.log('[MCP-Publisher] pollForToolsAfterOAuth: start', { maxTries, delayMs, server: this.oauthFlow?.server_name });
|
|
512
|
+
for (let i = 0; i < maxTries && (!this.discoveredTools || this.discoveredTools.length === 0); i++) {
|
|
513
|
+
try {
|
|
514
|
+
const statusResp = await fetch(`/admin/mcp/oauth-status/${this.oauthFlow.server_name}`);
|
|
515
|
+
const status = statusResp.ok ? await statusResp.json() : null;
|
|
516
|
+
console.log(`[MCP-Publisher] pollForToolsAfterOAuth: try ${i+1} status`, status);
|
|
517
|
+
if (status && status.status === 'connected') {
|
|
518
|
+
const recheck = await fetch('/admin/mcp/test-remote', {
|
|
519
|
+
method: 'POST',
|
|
520
|
+
headers: { 'Content-Type': 'application/json' },
|
|
521
|
+
body: JSON.stringify({ url: this.remoteUrl, name: this.oauthFlow.server_name })
|
|
522
|
+
});
|
|
523
|
+
const reData = await recheck.json();
|
|
524
|
+
console.log('[MCP-Publisher] pollForToolsAfterOAuth: test-remote response', reData);
|
|
525
|
+
if (reData.success && Array.isArray(reData.tools) && reData.tools.length) {
|
|
526
|
+
this.discoveredTools = reData.tools;
|
|
527
|
+
console.log('[MCP-Publisher] pollForToolsAfterOAuth: tools discovered', this.discoveredTools);
|
|
528
|
+
return true;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
} catch (e) {
|
|
532
|
+
console.warn('[MCP-Publisher] pollForToolsAfterOAuth: error', e);
|
|
533
|
+
}
|
|
534
|
+
await new Promise(res => setTimeout(res, delayMs));
|
|
535
|
+
}
|
|
536
|
+
console.log('[MCP-Publisher] pollForToolsAfterOAuth: end, tools found?', this.discoveredTools?.length);
|
|
537
|
+
return false;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
async publishServer() {
|
|
541
|
+
if (!this.serverName.trim()) {
|
|
542
|
+
this.error = "Server name is required";
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
if (!this.serverDescription.trim()) {
|
|
547
|
+
this.error = "Server description is required";
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (this.discoveredTools.length === 0) {
|
|
552
|
+
this.error = "Please discover tools first";
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (!this.isLoggedIn || !this.authToken) {
|
|
557
|
+
this.error = "Please log in to the registry first (top of page).";
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if (!this.registryUrl) {
|
|
562
|
+
this.error = "Registry URL is not configured.";
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
this.loading = true;
|
|
567
|
+
this.error = "";
|
|
568
|
+
this.success = "";
|
|
569
|
+
|
|
570
|
+
try {
|
|
571
|
+
// Prepare server configuration based on type
|
|
572
|
+
const serverData = {
|
|
573
|
+
name: this.serverName,
|
|
574
|
+
description: this.serverDescription,
|
|
575
|
+
server_type: this.serverType,
|
|
576
|
+
tools: this.discoveredTools,
|
|
577
|
+
transport: this.serverType === 'local' ? 'stdio' : 'http',
|
|
578
|
+
auth_type: this.serverType === 'local' ? 'none' : this.authType
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
// Add type-specific configuration
|
|
582
|
+
if (this.serverType === "local") {
|
|
583
|
+
Object.assign(serverData, {
|
|
584
|
+
command: this.localConfig.command,
|
|
585
|
+
args: this.localConfig.args,
|
|
586
|
+
env: this.localConfig.env
|
|
587
|
+
});
|
|
588
|
+
} else {
|
|
589
|
+
Object.assign(serverData, {
|
|
590
|
+
url: this.remoteUrl
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Build registry publish payload (align with registry ContentCreate)
|
|
595
|
+
const publishData = {
|
|
596
|
+
title: this.serverName,
|
|
597
|
+
description: this.serverDescription,
|
|
598
|
+
category: "mcp_server",
|
|
599
|
+
content_type: "mcp_server",
|
|
600
|
+
version: "1.0.0",
|
|
601
|
+
data: serverData,
|
|
602
|
+
tags: ["mcp", "server", this.serverType],
|
|
603
|
+
dependencies: []
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
const response = await fetch(`${this.registryUrl}/publish`, {
|
|
607
|
+
method: "POST",
|
|
608
|
+
headers: {
|
|
609
|
+
"Content-Type": "application/json",
|
|
610
|
+
"Authorization": `Bearer ${this.authToken}`
|
|
611
|
+
},
|
|
612
|
+
body: JSON.stringify(publishData)
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
if (response.ok) {
|
|
616
|
+
const result = await response.json();
|
|
617
|
+
this.success = result.message || `MCP Server "${this.serverName}" published successfully!`;
|
|
618
|
+
this.resetForm();
|
|
619
|
+
} else {
|
|
620
|
+
const errorData = await response.json();
|
|
621
|
+
throw new Error(errorData.detail || "Publishing failed");
|
|
622
|
+
}
|
|
623
|
+
} catch (error) {
|
|
624
|
+
this.error = `Publishing failed: ${error.message}`;
|
|
625
|
+
} finally {
|
|
626
|
+
this.loading = false;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
resetForm() {
|
|
631
|
+
this.serverName = '';
|
|
632
|
+
this.serverDescription = '';
|
|
633
|
+
this.localConfig = { command: '', args: [], env: {} };
|
|
634
|
+
this.remoteUrl = '';
|
|
635
|
+
this.discoveredTools = [];
|
|
636
|
+
this.oauthFlow = null;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
_render() {
|
|
640
|
+
return html`
|
|
641
|
+
<div class="mcp-publisher">
|
|
642
|
+
<div class="section">
|
|
643
|
+
<h3>Publish MCP Server</h3>
|
|
644
|
+
|
|
645
|
+
${this.error ? html`<div class="error">${this.error}</div>` : ''}
|
|
646
|
+
${this.success ? html`<div class="success">${this.success}</div>` : ''}
|
|
647
|
+
${this.oauthFlow ? html`<div class="oauth-status">OAuth flow in progress...</div>` : ''}
|
|
648
|
+
|
|
649
|
+
<div class="form-group">
|
|
650
|
+
<label>Server Name</label>
|
|
651
|
+
<input type="text"
|
|
652
|
+
.value=${this.serverName}
|
|
653
|
+
@input=${(e) => this.serverName = e.target.value}
|
|
654
|
+
placeholder="my-awesome-server">
|
|
655
|
+
</div>
|
|
656
|
+
|
|
657
|
+
<div class="form-group">
|
|
658
|
+
<label>Description</label>
|
|
659
|
+
<textarea .value=${this.serverDescription}
|
|
660
|
+
@input=${(e) => this.serverDescription = e.target.value}
|
|
661
|
+
placeholder="Describe what this MCP server does..."></textarea>
|
|
662
|
+
</div>
|
|
663
|
+
|
|
664
|
+
<div class="form-group">
|
|
665
|
+
<label>Server Type</label>
|
|
666
|
+
<div class="checkbox-group">
|
|
667
|
+
<div class="checkbox-item">
|
|
668
|
+
<input type="radio"
|
|
669
|
+
name="serverType"
|
|
670
|
+
value="local"
|
|
671
|
+
.checked=${this.serverType === 'local'}
|
|
672
|
+
@change=${this.handleServerTypeChange}>
|
|
673
|
+
<label>Local (stdio)</label>
|
|
674
|
+
</div>
|
|
675
|
+
<div class="checkbox-item">
|
|
676
|
+
<input type="radio"
|
|
677
|
+
name="serverType"
|
|
678
|
+
value="remote"
|
|
679
|
+
.checked=${this.serverType === 'remote'}
|
|
680
|
+
@change=${this.handleServerTypeChange}>
|
|
681
|
+
<label>Remote (HTTP/SSE)</label>
|
|
682
|
+
</div>
|
|
683
|
+
</div>
|
|
684
|
+
</div>
|
|
685
|
+
|
|
686
|
+
${this.serverType === 'local' ? this.renderLocalConfig() : this.renderRemoteConfig()}
|
|
687
|
+
${this.serverType === 'local' && this.requiredPlaceholders.length > 0 ? this.renderPlaceholderInputs() : ''}
|
|
688
|
+
|
|
689
|
+
<div class="form-row">
|
|
690
|
+
<button @click=${this.discoverTools} ?disabled=${this.loading} class="primary">
|
|
691
|
+
${this.loading ? 'Discovering...' : 'Discover & Connect'}
|
|
692
|
+
</button>
|
|
693
|
+
</div>
|
|
694
|
+
|
|
695
|
+
${this.discoveredTools.length > 0 ? this.renderToolsPreview() : ''}
|
|
696
|
+
</div>
|
|
697
|
+
</div>
|
|
698
|
+
`;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
renderLocalConfig() {
|
|
702
|
+
const exampleConfig = {
|
|
703
|
+
command: "npx",
|
|
704
|
+
args: ["-y", "slack-mcp-server@latest"],
|
|
705
|
+
env: {
|
|
706
|
+
"SLACK_MCP_XOXP_TOKEN": "xoxp-YOUR-TOKEN-HERE"
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
|
|
710
|
+
return html`
|
|
711
|
+
<div class="form-group">
|
|
712
|
+
<label>Local Server Configuration (JSON)</label>
|
|
713
|
+
<textarea @input=${this.handleLocalConfigChange} placeholder="Enter JSON configuration...">${JSON.stringify(this.localConfig, null, 2)}</textarea>
|
|
714
|
+
<div class="help-text">
|
|
715
|
+
<strong style='color: #ffc107;'>Warning:</strong> Do not paste real secrets here. Use placeholder values. The form below will prompt for the actual secrets, which are not stored in this text block.
|
|
716
|
+
</div>
|
|
717
|
+
<div class="help-text" style="margin-top: 1rem;">
|
|
718
|
+
Configure the command, arguments, and environment variables for your local MCP server.
|
|
719
|
+
</div>
|
|
720
|
+
<div class="json-example">
|
|
721
|
+
Example:
|
|
722
|
+
${JSON.stringify(exampleConfig, null, 2)}
|
|
723
|
+
</div>
|
|
724
|
+
</div>
|
|
725
|
+
`;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
renderPlaceholderInputs() {
|
|
729
|
+
return html`
|
|
730
|
+
<div class="section" style="margin-top: 1rem;">
|
|
731
|
+
<h4>Provide Environment Variables</h4>
|
|
732
|
+
<p class="help-text">Provide values for the environment variables found in your configuration. These values are not published to the registry but are stored locally for convenience.</p>
|
|
733
|
+
${this.requiredPlaceholders.map(placeholder => html`
|
|
734
|
+
<div class="form-group">
|
|
735
|
+
<label for="placeholder-${placeholder}">${placeholder}</label>
|
|
736
|
+
<input type="password"
|
|
737
|
+
id="placeholder-${placeholder}"
|
|
738
|
+
.value=${this.placeholderValues[placeholder] || ''}
|
|
739
|
+
@input=${e => this.placeholderValues = { ...this.placeholderValues, [placeholder]: e.target.value }} autocomplete="off">
|
|
740
|
+
</div>
|
|
741
|
+
`)}
|
|
742
|
+
</div>
|
|
743
|
+
`;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
renderRemoteConfig() {
|
|
747
|
+
return html`
|
|
748
|
+
<div class="form-group">
|
|
749
|
+
<label>Remote Server URL</label>
|
|
750
|
+
<input type="url"
|
|
751
|
+
.value=${this.remoteUrl}
|
|
752
|
+
@input=${(e) => this.remoteUrl = e.target.value}
|
|
753
|
+
placeholder="https://your-mcp-server.com/mcp">
|
|
754
|
+
<div class="help-text">
|
|
755
|
+
Enter the HTTP endpoint for your remote MCP server. OAuth authentication will be handled automatically if required.
|
|
756
|
+
</div>
|
|
757
|
+
</div>
|
|
758
|
+
`;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
renderToolsPreview() {
|
|
762
|
+
return html`
|
|
763
|
+
<div class="tools-preview">
|
|
764
|
+
<h4>Discovered Tools (${this.discoveredTools.length})</h4>
|
|
765
|
+
<div class="form-row">
|
|
766
|
+
<button class="primary" @click=${this.publishServer} ?disabled=${this.loading}>
|
|
767
|
+
${this.loading ? 'Publishing...' : 'Publish Server'}
|
|
768
|
+
</button>
|
|
769
|
+
</div>
|
|
770
|
+
${this.discoveredTools.map(tool => html`
|
|
771
|
+
<div class="tool-item">
|
|
772
|
+
<div class="tool-name">${tool.name}</div>
|
|
773
|
+
</div>
|
|
774
|
+
`)}
|
|
775
|
+
</div>
|
|
776
|
+
`;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
customElements.define('mcp-publisher', McpPublisher);
|