@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 CHANGED
@@ -1,8 +1,8 @@
1
- # TianGong-AI-MCP
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 AI Model Context Protocol (MCP) Server supports STDIO, SSE and StreamableHttp protocols.
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
- ## Development
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
- ### Local Testing
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
- #### SSE Server
44
+ ### Streamable Http Server
82
45
 
83
46
  ```bash
84
- # Build and package the project
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
- ### scaffold
50
+ ### Launch MCP Inspector
111
51
 
112
52
  ```bash
113
- npx tsx src/tools/openlca_ipc_test.ts
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>