@tiangong-lca/mcp-server 0.0.8 → 0.0.10
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 +8 -68
- package/dist/public/oauth-demo.html +371 -0
- package/dist/public/oauth-index.html +134 -0
- package/dist/src/_shared/auth_middleware.js +55 -5
- package/dist/src/_shared/cognito_auth.js +33 -0
- package/dist/src/_shared/config.js +13 -4
- package/dist/src/_shared/init_server.js +7 -1
- package/dist/src/_shared/init_server_http.js +7 -4
- package/dist/src/auth_app.js +356 -0
- package/dist/src/index_server.js +29 -0
- package/dist/src/prompts/lca_calculation.js +19 -0
- package/dist/src/resources/lca_calculation.js +16 -0
- package/dist/src/tools/flow_hybrid_search.js +12 -5
- package/dist/src/tools/lca_calculation_guidance.js +19 -0
- package/dist/src/tools/process_hybrid_search.js +5 -5
- package/package.json +13 -12
- package/dist/src/tools/_shared/clean_object.js +0 -22
- package/dist/src/tools/_shared/config.js +0 -4
- package/dist/src/tools/openlca_ipc copy.js +0 -1
- package/dist/src/tools/openlca_ipc.js +0 -57
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# TianGong-
|
|
1
|
+
# TianGong-LCA-MCP
|
|
2
2
|
|
|
3
3
|
[中文](https://github.com/linancn/tiangong-lca-mcp/blob/main/README_CN.md) | [English](https://github.com/linancn/tiangong-lca-mcp/blob/main/README.md)
|
|
4
4
|
|
|
5
|
-
TianGong
|
|
5
|
+
TianGong LCA Model Context Protocol (MCP) Server supports STDIO and Streamable Http protocols.
|
|
6
6
|
|
|
7
7
|
## Starting MCP Server
|
|
8
8
|
|
|
@@ -15,19 +15,6 @@ npx dotenv -e .env -- \
|
|
|
15
15
|
npx -p @tiangong-lca/mcp-server tiangong-lca-mcp-stdio
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
### Remote SSE Server
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
npm install -g @tiangong-lca/mcp-server
|
|
22
|
-
npm install -g supergateway
|
|
23
|
-
|
|
24
|
-
npx dotenv -e .env -- \
|
|
25
|
-
npx -y supergateway \
|
|
26
|
-
--stdio "npx -y -p @tiangong-lca/mcp-server tiangong-lca-mcp-stdio" \
|
|
27
|
-
--port 3001 \
|
|
28
|
-
--ssePath /sse --messagePath /message
|
|
29
|
-
```
|
|
30
|
-
|
|
31
18
|
### Using Docker
|
|
32
19
|
|
|
33
20
|
```bash
|
|
@@ -45,70 +32,23 @@ docker run -d \
|
|
|
45
32
|
linancn/tiangong-lca-mcp-server:0.0.5
|
|
46
33
|
```
|
|
47
34
|
|
|
48
|
-
##
|
|
49
|
-
|
|
50
|
-
### Environment Setup
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
# Install Node.js
|
|
54
|
-
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash
|
|
55
|
-
nvm install 22
|
|
56
|
-
nvm use
|
|
57
|
-
|
|
58
|
-
# Install dependencies
|
|
59
|
-
npm install
|
|
60
|
-
|
|
61
|
-
# Update dependencies
|
|
62
|
-
npm update && npm ci
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### Code Formatting
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
# Format code using the linter
|
|
69
|
-
npm run lint
|
|
70
|
-
```
|
|
35
|
+
## Local Testing
|
|
71
36
|
|
|
72
|
-
###
|
|
73
|
-
|
|
74
|
-
#### STDIO Server
|
|
37
|
+
### STDIO Server
|
|
75
38
|
|
|
76
39
|
```bash
|
|
77
40
|
# Launch the STDIO Server using MCP Inspector
|
|
78
41
|
npm start
|
|
79
42
|
```
|
|
80
43
|
|
|
81
|
-
|
|
44
|
+
### Streamable Http Server
|
|
82
45
|
|
|
83
46
|
```bash
|
|
84
|
-
|
|
85
|
-
npm run build && npm pack
|
|
86
|
-
|
|
87
|
-
# Optionally, install supergateway globally
|
|
88
|
-
npm install -g supergateway
|
|
89
|
-
|
|
90
|
-
# Launch the SSE Server (If the parameter --baseUrl is configured, it should be set to a valid IP address or domain name)
|
|
91
|
-
npx dotenv -e .env -- \
|
|
92
|
-
npx -y supergateway \
|
|
93
|
-
--stdio "npx -y -p tiangong-lca-mcp-server-0.0.5.tgz tiangong-lca-mcp-stdio" \
|
|
94
|
-
--port 3001 \
|
|
95
|
-
--ssePath /sse \
|
|
96
|
-
--messagePath /message
|
|
97
|
-
|
|
98
|
-
# Launch MCP Inspector
|
|
99
|
-
npx @modelcontextprotocol/inspector
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Publishing
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
npm login
|
|
106
|
-
|
|
107
|
-
npm run build && npm publish
|
|
47
|
+
npm run start:server
|
|
108
48
|
```
|
|
109
49
|
|
|
110
|
-
###
|
|
50
|
+
### Launch MCP Inspector
|
|
111
51
|
|
|
112
52
|
```bash
|
|
113
|
-
npx
|
|
53
|
+
DANGEROUSLY_OMIT_AUTH=true npx @modelcontextprotocol/inspector
|
|
114
54
|
```
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>OAuth Authentication Demo - Tiangong LCA MCP</title>
|
|
6
|
+
<style>
|
|
7
|
+
body {
|
|
8
|
+
font-family: Arial, sans-serif;
|
|
9
|
+
margin: 40px;
|
|
10
|
+
background-color: #f5f5f5;
|
|
11
|
+
}
|
|
12
|
+
.container {
|
|
13
|
+
max-width: 800px;
|
|
14
|
+
margin: 0 auto;
|
|
15
|
+
background: white;
|
|
16
|
+
padding: 30px;
|
|
17
|
+
border-radius: 8px;
|
|
18
|
+
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
19
|
+
}
|
|
20
|
+
.header {
|
|
21
|
+
text-align: center;
|
|
22
|
+
margin-bottom: 40px;
|
|
23
|
+
color: #333;
|
|
24
|
+
}
|
|
25
|
+
.section {
|
|
26
|
+
margin: 30px 0;
|
|
27
|
+
padding: 20px;
|
|
28
|
+
border: 1px solid #ddd;
|
|
29
|
+
border-radius: 6px;
|
|
30
|
+
background-color: #fafafa;
|
|
31
|
+
}
|
|
32
|
+
.section h3 {
|
|
33
|
+
color: #1976d2;
|
|
34
|
+
margin-top: 0;
|
|
35
|
+
}
|
|
36
|
+
button {
|
|
37
|
+
background: #1976d2;
|
|
38
|
+
color: white;
|
|
39
|
+
border: none;
|
|
40
|
+
padding: 12px 24px;
|
|
41
|
+
border-radius: 4px;
|
|
42
|
+
cursor: pointer;
|
|
43
|
+
font-size: 14px;
|
|
44
|
+
font-weight: bold;
|
|
45
|
+
transition: background-color 0.3s;
|
|
46
|
+
}
|
|
47
|
+
button:hover {
|
|
48
|
+
background: #1565c0;
|
|
49
|
+
}
|
|
50
|
+
button:disabled {
|
|
51
|
+
background: #ccc;
|
|
52
|
+
cursor: not-allowed;
|
|
53
|
+
}
|
|
54
|
+
input[type="text"] {
|
|
55
|
+
width: 100%;
|
|
56
|
+
max-width: 500px;
|
|
57
|
+
padding: 10px;
|
|
58
|
+
border: 1px solid #ddd;
|
|
59
|
+
border-radius: 4px;
|
|
60
|
+
font-size: 14px;
|
|
61
|
+
margin: 10px 0;
|
|
62
|
+
}
|
|
63
|
+
.result {
|
|
64
|
+
background-color: #e3f2fd;
|
|
65
|
+
padding: 15px;
|
|
66
|
+
margin: 15px 0;
|
|
67
|
+
border-radius: 4px;
|
|
68
|
+
border-left: 4px solid #1976d2;
|
|
69
|
+
}
|
|
70
|
+
.error {
|
|
71
|
+
background-color: #ffebee;
|
|
72
|
+
color: #c62828;
|
|
73
|
+
border-left: 4px solid #c62828;
|
|
74
|
+
padding: 8px;
|
|
75
|
+
}
|
|
76
|
+
.success {
|
|
77
|
+
background-color: #e8f5e8;
|
|
78
|
+
color: #2e7d32;
|
|
79
|
+
border-left: 4px solid #2e7d32;
|
|
80
|
+
padding: 8px;
|
|
81
|
+
}
|
|
82
|
+
.code-display {
|
|
83
|
+
font-family: monospace;
|
|
84
|
+
background: #f5f5f5;
|
|
85
|
+
padding: 10px;
|
|
86
|
+
border-radius: 4px;
|
|
87
|
+
word-break: break-all;
|
|
88
|
+
margin: 10px 0;
|
|
89
|
+
}
|
|
90
|
+
.back-link {
|
|
91
|
+
color: #1976d2;
|
|
92
|
+
text-decoration: none;
|
|
93
|
+
font-weight: bold;
|
|
94
|
+
display: inline-flex;
|
|
95
|
+
align-items: center;
|
|
96
|
+
gap: 5px;
|
|
97
|
+
}
|
|
98
|
+
.back-link:hover {
|
|
99
|
+
text-decoration: underline;
|
|
100
|
+
}
|
|
101
|
+
.info-box {
|
|
102
|
+
background: #e3f2fd;
|
|
103
|
+
border: 1px solid #90caf9;
|
|
104
|
+
border-radius: 4px;
|
|
105
|
+
padding: 15px;
|
|
106
|
+
margin: 15px 0;
|
|
107
|
+
}
|
|
108
|
+
</style>
|
|
109
|
+
</head>
|
|
110
|
+
<body>
|
|
111
|
+
<div class="container">
|
|
112
|
+
<div class="header">
|
|
113
|
+
<h1>🔐 OAuth Authentication Demo</h1>
|
|
114
|
+
<p>Interactive demonstration of AWS Cognito OAuth flow for Tiangong LCA MCP Server</p>
|
|
115
|
+
<a href="/oauth/index" class="back-link">← Back to Main Page</a>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div class="section">
|
|
119
|
+
<h2>📋 Authentication Workflow</h2>
|
|
120
|
+
|
|
121
|
+
<h3>🔄 Step 1: Start OAuth Authorization Flow</h3>
|
|
122
|
+
<p>Initiate the OAuth process and redirect to AWS Cognito hosted UI</p>
|
|
123
|
+
|
|
124
|
+
<h3>🔑 Step 2: Complete Login on Cognito</h3>
|
|
125
|
+
<p>Sign in using your credentials on the secure Cognito login page</p>
|
|
126
|
+
|
|
127
|
+
<h3>🔄 Step 3: Exchange Authorization Code</h3>
|
|
128
|
+
<p>Trade the authorization code for an access token using PKCE</p>
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<div class="section">
|
|
132
|
+
<h2>🚀 Quick Start</h2>
|
|
133
|
+
<ol>
|
|
134
|
+
<li>Click "Start OAuth Flow" below to begin authentication</li>
|
|
135
|
+
<li>Complete login on the Cognito hosted UI</li>
|
|
136
|
+
<li>Return here and paste the authorization code to get your access token</li>
|
|
137
|
+
</ol>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<div class="section">
|
|
141
|
+
<h3>🚀 Start OAuth Authorization</h3>
|
|
142
|
+
<p>Click the button below to begin the OAuth authorization process. This will redirect you to the AWS Cognito hosted login page.</p>
|
|
143
|
+
<button onclick="startOAuthFlow()">Start OAuth Flow</button>
|
|
144
|
+
<div id="oauth-result" class="result" style="display: none;"></div>
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<div class="section">
|
|
148
|
+
<h3>🔄 Exchange Authorization Code</h3>
|
|
149
|
+
<p>After completing the OAuth flow, paste the authorization code here to exchange it for an access token:</p>
|
|
150
|
+
<input type="text" id="auth-code" placeholder="Paste your authorization code here">
|
|
151
|
+
<br>
|
|
152
|
+
<button onclick="exchangeCodeForToken()">Exchange for Token</button>
|
|
153
|
+
<div id="exchange-result" class="result" style="display: none;"></div>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
|
|
157
|
+
<script>
|
|
158
|
+
const BASE_URL = 'https://lcamcp.tiangong.earth';
|
|
159
|
+
|
|
160
|
+
// PKCE helper functions
|
|
161
|
+
function generateCodeVerifier() {
|
|
162
|
+
const array = new Uint8Array(32);
|
|
163
|
+
crypto.getRandomValues(array);
|
|
164
|
+
return btoa(String.fromCharCode(...array))
|
|
165
|
+
.replace(/\+/g, '-')
|
|
166
|
+
.replace(/\//g, '_')
|
|
167
|
+
.replace(/=/g, '');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function generateCodeChallenge(codeVerifier) {
|
|
171
|
+
const encoder = new TextEncoder();
|
|
172
|
+
const data = encoder.encode(codeVerifier);
|
|
173
|
+
const digest = await crypto.subtle.digest('SHA-256', data);
|
|
174
|
+
return btoa(String.fromCharCode(...new Uint8Array(digest)))
|
|
175
|
+
.replace(/\+/g, '-')
|
|
176
|
+
.replace(/\//g, '_')
|
|
177
|
+
.replace(/=/g, '');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function startOAuthFlow() {
|
|
181
|
+
const resultDiv = document.getElementById('oauth-result');
|
|
182
|
+
resultDiv.style.display = 'block';
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
// Generate PKCE parameters
|
|
186
|
+
const codeVerifier = generateCodeVerifier();
|
|
187
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
188
|
+
|
|
189
|
+
// Save code_verifier to localStorage for later token exchange
|
|
190
|
+
localStorage.setItem('code_verifier', codeVerifier);
|
|
191
|
+
|
|
192
|
+
// Build authorization URL - directly use Cognito domain
|
|
193
|
+
const authUrl = new URL('https://us-east-1snsyimond.auth.us-east-1.amazoncognito.com/oauth2/authorize');
|
|
194
|
+
authUrl.searchParams.append('client_id', '3p182unuqch7rahbp0trs1sprv');
|
|
195
|
+
authUrl.searchParams.append('response_type', 'code');
|
|
196
|
+
authUrl.searchParams.append('scope', 'openid email profile');
|
|
197
|
+
authUrl.searchParams.append('redirect_uri', 'https://lcamcp.tiangong.earth/oauth/callback');
|
|
198
|
+
authUrl.searchParams.append('code_challenge', codeChallenge);
|
|
199
|
+
authUrl.searchParams.append('code_challenge_method', 'S256');
|
|
200
|
+
|
|
201
|
+
resultDiv.innerHTML = `
|
|
202
|
+
<div class="success">
|
|
203
|
+
<p><strong>✅ Redirecting to authorization page...</strong></p>
|
|
204
|
+
<p>Opening Cognito login page in a new window</p>
|
|
205
|
+
<div class="info-box">
|
|
206
|
+
<p><strong>Generated PKCE Parameters:</strong></p>
|
|
207
|
+
<div class="code-display">Code Verifier: ${codeVerifier}</div>
|
|
208
|
+
<div class="code-display">Code Challenge: ${codeChallenge}</div>
|
|
209
|
+
</div>
|
|
210
|
+
<p><em>💡 Tip: Complete the login process in the new window, then return here to exchange your authorization code.</em></p>
|
|
211
|
+
</div>
|
|
212
|
+
`;
|
|
213
|
+
|
|
214
|
+
// Open authorization page in new window
|
|
215
|
+
setTimeout(() => {
|
|
216
|
+
window.open(authUrl.toString(), '_blank');
|
|
217
|
+
}, 1000);
|
|
218
|
+
|
|
219
|
+
} catch (error) {
|
|
220
|
+
resultDiv.innerHTML = `
|
|
221
|
+
<div class="error">
|
|
222
|
+
<p><strong>❌ Failed to generate PKCE parameters</strong></p>
|
|
223
|
+
<p>Error: ${error.message}</p>
|
|
224
|
+
</div>
|
|
225
|
+
`;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function exchangeCodeForToken() {
|
|
230
|
+
const code = document.getElementById('auth-code').value;
|
|
231
|
+
const resultDiv = document.getElementById('exchange-result');
|
|
232
|
+
const codeVerifier = localStorage.getItem('code_verifier');
|
|
233
|
+
|
|
234
|
+
resultDiv.style.display = 'block';
|
|
235
|
+
|
|
236
|
+
if (!code.trim()) {
|
|
237
|
+
resultDiv.innerHTML = '<div class="error"><p><strong>❌ Please enter the authorization code</strong></p></div>';
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (!codeVerifier) {
|
|
242
|
+
resultDiv.innerHTML = '<div class="error"><p><strong>❌ Code verifier not found</strong></p><p>Please restart the OAuth flow first.</p></div>';
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Show loading state
|
|
247
|
+
resultDiv.innerHTML = '<div class="result"><p>🔄 Exchanging authorization code for access token...</p></div>';
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
const response = await fetch(`${BASE_URL}/oauth/token`, {
|
|
251
|
+
method: 'POST',
|
|
252
|
+
headers: {
|
|
253
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
254
|
+
},
|
|
255
|
+
body: new URLSearchParams({
|
|
256
|
+
grant_type: 'authorization_code',
|
|
257
|
+
client_id: '3p182unuqch7rahbp0trs1sprv',
|
|
258
|
+
code: code.trim(),
|
|
259
|
+
redirect_uri: 'https://lcamcp.tiangong.earth/oauth/callback',
|
|
260
|
+
code_verifier: codeVerifier,
|
|
261
|
+
}),
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
const contentType = response.headers.get('content-type');
|
|
265
|
+
|
|
266
|
+
if (response.ok) {
|
|
267
|
+
if (contentType && contentType.includes('application/json')) {
|
|
268
|
+
const data = await response.json();
|
|
269
|
+
resultDiv.innerHTML = `
|
|
270
|
+
<div class="success">
|
|
271
|
+
<p><strong>🎉 Token exchange successful!</strong></p>
|
|
272
|
+
<div class="info-box">
|
|
273
|
+
<p><strong>Access Token:</strong></p>
|
|
274
|
+
<div class="code-display">${data.access_token}</div>
|
|
275
|
+
<p><strong>Token Type:</strong> ${data.token_type}</p>
|
|
276
|
+
<p><strong>Expires In:</strong> ${data.expires_in} seconds</p>
|
|
277
|
+
${data.refresh_token ? `<p><strong>Refresh Token:</strong></p><div class="code-display">${data.refresh_token}</div>` : ''}
|
|
278
|
+
</div>
|
|
279
|
+
<p><em>💡 You can now use this access token to make authenticated requests to the MCP endpoint.</em></p>
|
|
280
|
+
</div>
|
|
281
|
+
`;
|
|
282
|
+
|
|
283
|
+
// Clear the stored code verifier
|
|
284
|
+
localStorage.removeItem('code_verifier');
|
|
285
|
+
|
|
286
|
+
} else {
|
|
287
|
+
const text = await response.text();
|
|
288
|
+
resultDiv.innerHTML = `
|
|
289
|
+
<div class="error">
|
|
290
|
+
<p><strong>❌ Unexpected response format</strong></p>
|
|
291
|
+
<p>Status: ${response.status}</p>
|
|
292
|
+
<p>Content-Type: ${contentType}</p>
|
|
293
|
+
<div class="code-display">${text.substring(0, 500)}${text.length > 500 ? '...' : ''}</div>
|
|
294
|
+
</div>
|
|
295
|
+
`;
|
|
296
|
+
}
|
|
297
|
+
} else {
|
|
298
|
+
const text = await response.text();
|
|
299
|
+
let errorMessage = text;
|
|
300
|
+
|
|
301
|
+
// Try to parse as JSON
|
|
302
|
+
try {
|
|
303
|
+
const errorJson = JSON.parse(text);
|
|
304
|
+
errorMessage = JSON.stringify(errorJson, null, 2);
|
|
305
|
+
} catch {
|
|
306
|
+
// If not JSON, keep original text
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
resultDiv.innerHTML = `
|
|
310
|
+
<div class="error">
|
|
311
|
+
<p><strong>❌ Token exchange failed</strong></p>
|
|
312
|
+
<p>Status: ${response.status}</p>
|
|
313
|
+
<div class="code-display">${errorMessage.substring(0, 500)}${errorMessage.length > 500 ? '...' : ''}</div>
|
|
314
|
+
</div>
|
|
315
|
+
`;
|
|
316
|
+
}
|
|
317
|
+
} catch (error) {
|
|
318
|
+
resultDiv.innerHTML = `
|
|
319
|
+
<div class="error">
|
|
320
|
+
<p><strong>❌ Request failed</strong></p>
|
|
321
|
+
<p>Error: ${error.message}</p>
|
|
322
|
+
<p>This might be a network connectivity issue or CORS configuration problem.</p>
|
|
323
|
+
<p><em>💡 Check the browser developer tools Network tab for detailed error information.</em></p>
|
|
324
|
+
</div>
|
|
325
|
+
`;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Check URL parameters for authorization code or error on page load
|
|
330
|
+
window.addEventListener('load', function() {
|
|
331
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
332
|
+
const code = urlParams.get('code');
|
|
333
|
+
const error = urlParams.get('error');
|
|
334
|
+
const errorDescription = urlParams.get('error_description');
|
|
335
|
+
|
|
336
|
+
if (error) {
|
|
337
|
+
const resultDiv = document.getElementById('oauth-result');
|
|
338
|
+
resultDiv.style.display = 'block';
|
|
339
|
+
resultDiv.innerHTML = `
|
|
340
|
+
<div class="error">
|
|
341
|
+
<p><strong>❌ OAuth authorization failed</strong></p>
|
|
342
|
+
<p>Error: ${error}</p>
|
|
343
|
+
<p>Description: ${decodeURIComponent(errorDescription || '')}</p>
|
|
344
|
+
</div>
|
|
345
|
+
`;
|
|
346
|
+
} else if (code) {
|
|
347
|
+
const codeVerifier = localStorage.getItem('code_verifier');
|
|
348
|
+
const resultDiv = document.getElementById('oauth-result');
|
|
349
|
+
resultDiv.style.display = 'block';
|
|
350
|
+
resultDiv.innerHTML = `
|
|
351
|
+
<div class="success">
|
|
352
|
+
<p><strong>✅ Authorization code received!</strong></p>
|
|
353
|
+
<div class="info-box">
|
|
354
|
+
<p><strong>Authorization Code:</strong></p>
|
|
355
|
+
<div class="code-display">${code}</div>
|
|
356
|
+
${codeVerifier ? `<p><strong>Code Verifier:</strong></p><div class="code-display">${codeVerifier}</div>` : ''}
|
|
357
|
+
</div>
|
|
358
|
+
<p><em>💡 The authorization code has been automatically filled in the exchange form below.</em></p>
|
|
359
|
+
</div>
|
|
360
|
+
`;
|
|
361
|
+
|
|
362
|
+
// Auto-fill the authorization code
|
|
363
|
+
document.getElementById('auth-code').value = code;
|
|
364
|
+
|
|
365
|
+
// Scroll to the exchange section
|
|
366
|
+
document.querySelector('[onclick="exchangeCodeForToken()"]').scrollIntoView({ behavior: 'smooth' });
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
</script>
|
|
370
|
+
</body>
|
|
371
|
+
</html>
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Tiangong LCA MCP Server</title>
|
|
6
|
+
<style>
|
|
7
|
+
body {
|
|
8
|
+
font-family: Arial, sans-serif;
|
|
9
|
+
margin: 40px;
|
|
10
|
+
background-color: #f5f5f5;
|
|
11
|
+
}
|
|
12
|
+
.container {
|
|
13
|
+
max-width: 800px;
|
|
14
|
+
margin: 0 auto;
|
|
15
|
+
background: white;
|
|
16
|
+
padding: 30px;
|
|
17
|
+
border-radius: 8px;
|
|
18
|
+
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
19
|
+
}
|
|
20
|
+
.header {
|
|
21
|
+
text-align: center;
|
|
22
|
+
margin-bottom: 40px;
|
|
23
|
+
color: #333;
|
|
24
|
+
}
|
|
25
|
+
.section {
|
|
26
|
+
margin: 30px 0;
|
|
27
|
+
padding: 20px;
|
|
28
|
+
border: 1px solid #ddd;
|
|
29
|
+
border-radius: 6px;
|
|
30
|
+
background-color: #fafafa;
|
|
31
|
+
}
|
|
32
|
+
.endpoint {
|
|
33
|
+
font-family: monospace;
|
|
34
|
+
background: #e3f2fd;
|
|
35
|
+
padding: 8px 12px;
|
|
36
|
+
border-radius: 4px;
|
|
37
|
+
display: inline-block;
|
|
38
|
+
margin: 5px 0;
|
|
39
|
+
}
|
|
40
|
+
.method {
|
|
41
|
+
font-weight: bold;
|
|
42
|
+
color: #1976d2;
|
|
43
|
+
}
|
|
44
|
+
.link {
|
|
45
|
+
color: #1976d2;
|
|
46
|
+
text-decoration: none;
|
|
47
|
+
font-weight: bold;
|
|
48
|
+
}
|
|
49
|
+
.link:hover {
|
|
50
|
+
text-decoration: underline;
|
|
51
|
+
}
|
|
52
|
+
.status {
|
|
53
|
+
display: inline-block;
|
|
54
|
+
padding: 4px 8px;
|
|
55
|
+
border-radius: 3px;
|
|
56
|
+
font-size: 12px;
|
|
57
|
+
font-weight: bold;
|
|
58
|
+
}
|
|
59
|
+
.available { background-color: #c8e6c9; color: #2e7d32; }
|
|
60
|
+
.auth-required { background-color: #fff3e0; color: #f57c00; }
|
|
61
|
+
</style>
|
|
62
|
+
</head>
|
|
63
|
+
<body>
|
|
64
|
+
<div class="container">
|
|
65
|
+
<div class="header">
|
|
66
|
+
<h1>🌐 Tiangong LCA MCP Server</h1>
|
|
67
|
+
<p>Model Context Protocol Server for Life Cycle Assessment</p>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div class="section">
|
|
71
|
+
<h2>📋 Available Endpoints</h2>
|
|
72
|
+
|
|
73
|
+
<h3>🔍 Health & Status</h3>
|
|
74
|
+
<div class="endpoint">
|
|
75
|
+
<span class="method">GET</span> /health
|
|
76
|
+
<span class="status available">Available</span>
|
|
77
|
+
</div>
|
|
78
|
+
<p>Check server health status</p>
|
|
79
|
+
|
|
80
|
+
<h3>🔐 OAuth Authentication</h3>
|
|
81
|
+
<div class="endpoint">
|
|
82
|
+
<span class="method">GET</span> /oauth/demo
|
|
83
|
+
<span class="status available">Available</span>
|
|
84
|
+
</div>
|
|
85
|
+
<p><a href="/oauth/demo" class="link">OAuth Demo Interface</a> - Interactive Cognito OAuth flow demonstration</p>
|
|
86
|
+
|
|
87
|
+
<div class="endpoint">
|
|
88
|
+
<span class="method">GET</span> /oauth/authorize
|
|
89
|
+
<span class="status available">Available</span>
|
|
90
|
+
</div>
|
|
91
|
+
<p>OAuth authorization endpoint</p>
|
|
92
|
+
|
|
93
|
+
<div class="endpoint">
|
|
94
|
+
<span class="method">GET</span> /oauth/callback
|
|
95
|
+
<span class="status available">Available</span>
|
|
96
|
+
</div>
|
|
97
|
+
<p>OAuth callback endpoint</p>
|
|
98
|
+
|
|
99
|
+
<div class="endpoint">
|
|
100
|
+
<span class="method">POST</span> /oauth/token
|
|
101
|
+
<span class="status available">Available</span>
|
|
102
|
+
</div>
|
|
103
|
+
<p>Token exchange endpoint (PKCE supported)</p>
|
|
104
|
+
|
|
105
|
+
<h3>🤖 MCP Protocol</h3>
|
|
106
|
+
<div class="endpoint">
|
|
107
|
+
<span class="method">POST</span> /mcp
|
|
108
|
+
<span class="status auth-required">Auth Required</span>
|
|
109
|
+
</div>
|
|
110
|
+
<p>Main MCP endpoint for tool interactions (requires Bearer token)</p>
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<div class="section">
|
|
114
|
+
<h2>🚀 Quick Start</h2>
|
|
115
|
+
<ol>
|
|
116
|
+
<li>Visit <a href="/oauth/demo" class="link">/oauth/demo</a> to test OAuth authentication</li>
|
|
117
|
+
<li>Complete the OAuth flow to get an access token</li>
|
|
118
|
+
<li>Use the access token to make requests to the <code>/mcp</code> endpoint</li>
|
|
119
|
+
</ol>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div class="section">
|
|
123
|
+
<h2>📖 Documentation</h2>
|
|
124
|
+
<p>For more information about the Model Context Protocol, visit the <a href="https://modelcontextprotocol.io" class="link" target="_blank">official documentation</a>.</p>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<div class="section">
|
|
128
|
+
<h2>🔧 Available Pages</h2>
|
|
129
|
+
<p>Main OAuth authentication interface: <a href="/oauth/index" class="link">/oauth/index</a></p>
|
|
130
|
+
<p>OAuth demo interface: <a href="/oauth/demo" class="link">/oauth/demo</a></p>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
</body>
|
|
134
|
+
</html>
|