feat(planning): grille hebdomadaire complète avec API et filtres
- Connexion API via proxy Angular (résolution CORS, base path /api) - Import CSS ng-zorro global pour les modales et composants - Filtres Camion/Show câblés sur l'affichage de la grille - Camions affichés via TrucksService (linkés au show du même créneau) - Panneau de détails : spectacles + camions du jour sélectionné - Modale de création de spectacle stylisée avec fond et centrage - Positionnement précis des events à la minute dans leur créneau - Auto-scroll vers l'heure courante au chargement - Ligne "maintenant" sur la colonne du jour actuel - Régénération des services OpenAPI (nouveaux noms de types) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Generated
Vendored
+122
-195
@@ -1,118 +1,83 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = __importDefault(require("express"));
|
||||
const node_crypto_1 = require("node:crypto");
|
||||
const z = __importStar(require("zod/v4"));
|
||||
const zod_1 = require("zod");
|
||||
const mcp_js_1 = require("../../server/mcp.js");
|
||||
const streamableHttp_js_1 = require("../../server/streamableHttp.js");
|
||||
const router_js_1 = require("../../server/auth/router.js");
|
||||
const bearerAuth_js_1 = require("../../server/auth/middleware/bearerAuth.js");
|
||||
const express_js_1 = require("../../server/express.js");
|
||||
const types_js_1 = require("../../types.js");
|
||||
const inMemoryEventStore_js_1 = require("../shared/inMemoryEventStore.js");
|
||||
const in_memory_js_1 = require("../../experimental/tasks/stores/in-memory.js");
|
||||
const demoInMemoryOAuthProvider_js_1 = require("./demoInMemoryOAuthProvider.js");
|
||||
const auth_utils_js_1 = require("../../shared/auth-utils.js");
|
||||
const auth_utils_js_1 = require("src/shared/auth-utils.js");
|
||||
const cors_1 = __importDefault(require("cors"));
|
||||
// Check for OAuth flag
|
||||
const useOAuth = process.argv.includes('--oauth');
|
||||
const strictOAuth = process.argv.includes('--oauth-strict');
|
||||
// Create shared task store for demonstration
|
||||
const taskStore = new in_memory_js_1.InMemoryTaskStore();
|
||||
// Create an MCP server with implementation details
|
||||
const getServer = () => {
|
||||
const server = new mcp_js_1.McpServer({
|
||||
name: 'simple-streamable-http-server',
|
||||
version: '1.0.0',
|
||||
icons: [{ src: './mcp.svg', sizes: ['512x512'], mimeType: 'image/svg+xml' }],
|
||||
websiteUrl: 'https://github.com/modelcontextprotocol/typescript-sdk'
|
||||
}, {
|
||||
capabilities: { logging: {}, tasks: { requests: { tools: { call: {} } } } },
|
||||
taskStore, // Enable task support
|
||||
taskMessageQueue: new in_memory_js_1.InMemoryTaskMessageQueue()
|
||||
});
|
||||
version: '1.0.0'
|
||||
}, { capabilities: { logging: {} } });
|
||||
// Register a simple tool that returns a greeting
|
||||
server.registerTool('greet', {
|
||||
title: 'Greeting Tool', // Display name for UI
|
||||
description: 'A simple greeting tool',
|
||||
inputSchema: {
|
||||
name: z.string().describe('Name to greet')
|
||||
}
|
||||
name: zod_1.z.string().describe('Name to greet'),
|
||||
},
|
||||
}, async ({ name }) => {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Hello, ${name}!`
|
||||
}
|
||||
]
|
||||
text: `Hello, ${name}!`,
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
// Register a tool that sends multiple greetings with notifications (with annotations)
|
||||
server.registerTool('multi-greet', {
|
||||
description: 'A tool that sends different greetings with delays between them',
|
||||
inputSchema: {
|
||||
name: z.string().describe('Name to greet')
|
||||
},
|
||||
annotations: {
|
||||
title: 'Multiple Greeting Tool',
|
||||
readOnlyHint: true,
|
||||
openWorldHint: false
|
||||
}
|
||||
}, async ({ name }, extra) => {
|
||||
server.tool('multi-greet', 'A tool that sends different greetings with delays between them', {
|
||||
name: zod_1.z.string().describe('Name to greet'),
|
||||
}, {
|
||||
title: 'Multiple Greeting Tool',
|
||||
readOnlyHint: true,
|
||||
openWorldHint: false
|
||||
}, async ({ name }, { sendNotification }) => {
|
||||
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
await server.sendLoggingMessage({
|
||||
level: 'debug',
|
||||
data: `Starting multi-greet for ${name}`
|
||||
}, extra.sessionId);
|
||||
await sendNotification({
|
||||
method: "notifications/message",
|
||||
params: { level: "debug", data: `Starting multi-greet for ${name}` }
|
||||
});
|
||||
await sleep(1000); // Wait 1 second before first greeting
|
||||
await server.sendLoggingMessage({
|
||||
level: 'info',
|
||||
data: `Sending first greeting to ${name}`
|
||||
}, extra.sessionId);
|
||||
await sendNotification({
|
||||
method: "notifications/message",
|
||||
params: { level: "info", data: `Sending first greeting to ${name}` }
|
||||
});
|
||||
await sleep(1000); // Wait another second before second greeting
|
||||
await server.sendLoggingMessage({
|
||||
level: 'info',
|
||||
data: `Sending second greeting to ${name}`
|
||||
}, extra.sessionId);
|
||||
await sendNotification({
|
||||
method: "notifications/message",
|
||||
params: { level: "info", data: `Sending second greeting to ${name}` }
|
||||
});
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Good morning, ${name}!`
|
||||
text: `Good morning, ${name}!`,
|
||||
}
|
||||
]
|
||||
],
|
||||
};
|
||||
});
|
||||
// Register a tool that demonstrates form elicitation (user input collection with a schema)
|
||||
// Register a tool that demonstrates elicitation (user input collection)
|
||||
// This creates a closure that captures the server instance
|
||||
server.registerTool('collect-user-info', {
|
||||
description: 'A tool that collects user information through form elicitation',
|
||||
inputSchema: {
|
||||
infoType: z.enum(['contact', 'preferences', 'feedback']).describe('Type of information to collect')
|
||||
}
|
||||
}, async ({ infoType }, extra) => {
|
||||
server.tool('collect-user-info', 'A tool that collects user information through elicitation', {
|
||||
infoType: zod_1.z.enum(['contact', 'preferences', 'feedback']).describe('Type of information to collect'),
|
||||
}, async ({ infoType }) => {
|
||||
let message;
|
||||
let requestedSchema;
|
||||
switch (infoType) {
|
||||
@@ -124,21 +89,21 @@ const getServer = () => {
|
||||
name: {
|
||||
type: 'string',
|
||||
title: 'Full Name',
|
||||
description: 'Your full name'
|
||||
description: 'Your full name',
|
||||
},
|
||||
email: {
|
||||
type: 'string',
|
||||
title: 'Email Address',
|
||||
description: 'Your email address',
|
||||
format: 'email'
|
||||
format: 'email',
|
||||
},
|
||||
phone: {
|
||||
type: 'string',
|
||||
title: 'Phone Number',
|
||||
description: 'Your phone number (optional)'
|
||||
}
|
||||
description: 'Your phone number (optional)',
|
||||
},
|
||||
},
|
||||
required: ['name', 'email']
|
||||
required: ['name', 'email'],
|
||||
};
|
||||
break;
|
||||
case 'preferences':
|
||||
@@ -151,23 +116,23 @@ const getServer = () => {
|
||||
title: 'Theme',
|
||||
description: 'Choose your preferred theme',
|
||||
enum: ['light', 'dark', 'auto'],
|
||||
enumNames: ['Light', 'Dark', 'Auto']
|
||||
enumNames: ['Light', 'Dark', 'Auto'],
|
||||
},
|
||||
notifications: {
|
||||
type: 'boolean',
|
||||
title: 'Enable Notifications',
|
||||
description: 'Would you like to receive notifications?',
|
||||
default: true
|
||||
default: true,
|
||||
},
|
||||
frequency: {
|
||||
type: 'string',
|
||||
title: 'Notification Frequency',
|
||||
description: 'How often would you like notifications?',
|
||||
enum: ['daily', 'weekly', 'monthly'],
|
||||
enumNames: ['Daily', 'Weekly', 'Monthly']
|
||||
}
|
||||
enumNames: ['Daily', 'Weekly', 'Monthly'],
|
||||
},
|
||||
},
|
||||
required: ['theme']
|
||||
required: ['theme'],
|
||||
};
|
||||
break;
|
||||
case 'feedback':
|
||||
@@ -180,44 +145,40 @@ const getServer = () => {
|
||||
title: 'Rating',
|
||||
description: 'Rate your experience (1-5)',
|
||||
minimum: 1,
|
||||
maximum: 5
|
||||
maximum: 5,
|
||||
},
|
||||
comments: {
|
||||
type: 'string',
|
||||
title: 'Comments',
|
||||
description: 'Additional comments (optional)',
|
||||
maxLength: 500
|
||||
maxLength: 500,
|
||||
},
|
||||
recommend: {
|
||||
type: 'boolean',
|
||||
title: 'Would you recommend this?',
|
||||
description: 'Would you recommend this to others?'
|
||||
}
|
||||
description: 'Would you recommend this to others?',
|
||||
},
|
||||
},
|
||||
required: ['rating', 'recommend']
|
||||
required: ['rating', 'recommend'],
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown info type: ${infoType}`);
|
||||
}
|
||||
try {
|
||||
// Use sendRequest through the extra parameter to elicit input
|
||||
const result = await extra.sendRequest({
|
||||
method: 'elicitation/create',
|
||||
params: {
|
||||
mode: 'form',
|
||||
message,
|
||||
requestedSchema
|
||||
}
|
||||
}, types_js_1.ElicitResultSchema);
|
||||
// Use the underlying server instance to elicit input from the client
|
||||
const result = await server.server.elicitInput({
|
||||
message,
|
||||
requestedSchema,
|
||||
});
|
||||
if (result.action === 'accept') {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Thank you! Collected ${infoType} information: ${JSON.stringify(result.content, null, 2)}`
|
||||
}
|
||||
]
|
||||
text: `Thank you! Collected ${infoType} information: ${JSON.stringify(result.content, null, 2)}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
else if (result.action === 'decline') {
|
||||
@@ -225,9 +186,9 @@ const getServer = () => {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `No information was collected. User declined ${infoType} information request.`
|
||||
}
|
||||
]
|
||||
text: `No information was collected. User declined ${infoType} information request.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
else {
|
||||
@@ -235,9 +196,9 @@ const getServer = () => {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Information collection was cancelled by the user.`
|
||||
}
|
||||
]
|
||||
text: `Information collection was cancelled by the user.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -246,9 +207,9 @@ const getServer = () => {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Error collecting ${infoType} information: ${error}`
|
||||
}
|
||||
]
|
||||
text: `Error collecting ${infoType} information: ${error}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -257,8 +218,8 @@ const getServer = () => {
|
||||
title: 'Greeting Template', // Display name for UI
|
||||
description: 'A simple greeting prompt template',
|
||||
argsSchema: {
|
||||
name: z.string().describe('Name to include in greeting')
|
||||
}
|
||||
name: zod_1.z.string().describe('Name to include in greeting'),
|
||||
},
|
||||
}, async ({ name }) => {
|
||||
return {
|
||||
messages: [
|
||||
@@ -266,32 +227,32 @@ const getServer = () => {
|
||||
role: 'user',
|
||||
content: {
|
||||
type: 'text',
|
||||
text: `Please greet ${name} in a friendly manner.`
|
||||
}
|
||||
}
|
||||
]
|
||||
text: `Please greet ${name} in a friendly manner.`,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
// Register a tool specifically for testing resumability
|
||||
server.registerTool('start-notification-stream', {
|
||||
description: 'Starts sending periodic notifications for testing resumability',
|
||||
inputSchema: {
|
||||
interval: z.number().describe('Interval in milliseconds between notifications').default(100),
|
||||
count: z.number().describe('Number of notifications to send (0 for 100)').default(50)
|
||||
}
|
||||
}, async ({ interval, count }, extra) => {
|
||||
server.tool('start-notification-stream', 'Starts sending periodic notifications for testing resumability', {
|
||||
interval: zod_1.z.number().describe('Interval in milliseconds between notifications').default(100),
|
||||
count: zod_1.z.number().describe('Number of notifications to send (0 for 100)').default(50),
|
||||
}, async ({ interval, count }, { sendNotification }) => {
|
||||
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
let counter = 0;
|
||||
while (count === 0 || counter < count) {
|
||||
counter++;
|
||||
try {
|
||||
await server.sendLoggingMessage({
|
||||
level: 'info',
|
||||
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
|
||||
}, extra.sessionId);
|
||||
await sendNotification({
|
||||
method: "notifications/message",
|
||||
params: {
|
||||
level: "info",
|
||||
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error sending notification:', error);
|
||||
console.error("Error sending notification:", error);
|
||||
}
|
||||
// Wait for the specified interval
|
||||
await sleep(interval);
|
||||
@@ -300,9 +261,9 @@ const getServer = () => {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Started sending periodic notifications every ${interval}ms`
|
||||
text: `Started sending periodic notifications every ${interval}ms`,
|
||||
}
|
||||
]
|
||||
],
|
||||
};
|
||||
});
|
||||
// Create a simple resource at a fixed URI
|
||||
@@ -315,9 +276,9 @@ const getServer = () => {
|
||||
contents: [
|
||||
{
|
||||
uri: 'https://example.com/greetings/default',
|
||||
text: 'Hello, world!'
|
||||
}
|
||||
]
|
||||
text: 'Hello, world!',
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
// Create additional resources for ResourceLink demonstration
|
||||
@@ -330,9 +291,9 @@ const getServer = () => {
|
||||
contents: [
|
||||
{
|
||||
uri: 'file:///example/file1.txt',
|
||||
text: 'This is the content of file 1'
|
||||
}
|
||||
]
|
||||
text: 'This is the content of file 1',
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
server.registerResource('example-file-2', 'file:///example/file2.txt', {
|
||||
@@ -344,9 +305,9 @@ const getServer = () => {
|
||||
contents: [
|
||||
{
|
||||
uri: 'file:///example/file2.txt',
|
||||
text: 'This is the content of file 2'
|
||||
}
|
||||
]
|
||||
text: 'This is the content of file 2',
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
// Register a tool that returns ResourceLinks
|
||||
@@ -354,8 +315,8 @@ const getServer = () => {
|
||||
title: 'List Files with ResourceLinks',
|
||||
description: 'Returns a list of files as ResourceLinks without embedding their content',
|
||||
inputSchema: {
|
||||
includeDescriptions: z.boolean().optional().describe('Whether to include descriptions in the resource links')
|
||||
}
|
||||
includeDescriptions: zod_1.z.boolean().optional().describe('Whether to include descriptions in the resource links'),
|
||||
},
|
||||
}, async ({ includeDescriptions = true }) => {
|
||||
const resourceLinks = [
|
||||
{
|
||||
@@ -384,60 +345,27 @@ const getServer = () => {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'Here are the available files as resource links:'
|
||||
text: 'Here are the available files as resource links:',
|
||||
},
|
||||
...resourceLinks,
|
||||
{
|
||||
type: 'text',
|
||||
text: '\nYou can read any of these resources using their URI.'
|
||||
text: '\nYou can read any of these resources using their URI.',
|
||||
}
|
||||
]
|
||||
],
|
||||
};
|
||||
});
|
||||
// Register a long-running tool that demonstrates task execution
|
||||
// Using the experimental tasks API - WARNING: may change without notice
|
||||
server.experimental.tasks.registerToolTask('delay', {
|
||||
title: 'Delay',
|
||||
description: 'A simple tool that delays for a specified duration, useful for testing task execution',
|
||||
inputSchema: {
|
||||
duration: z.number().describe('Duration in milliseconds').default(5000)
|
||||
}
|
||||
}, {
|
||||
async createTask({ duration }, { taskStore, taskRequestedTtl }) {
|
||||
// Create the task
|
||||
const task = await taskStore.createTask({
|
||||
ttl: taskRequestedTtl
|
||||
});
|
||||
// Simulate out-of-band work
|
||||
(async () => {
|
||||
await new Promise(resolve => setTimeout(resolve, duration));
|
||||
await taskStore.storeTaskResult(task.taskId, 'completed', {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Completed ${duration}ms delay`
|
||||
}
|
||||
]
|
||||
});
|
||||
})();
|
||||
// Return CreateTaskResult with the created task
|
||||
return {
|
||||
task
|
||||
};
|
||||
},
|
||||
async getTask(_args, { taskId, taskStore }) {
|
||||
return await taskStore.getTask(taskId);
|
||||
},
|
||||
async getTaskResult(_args, { taskId, taskStore }) {
|
||||
const result = await taskStore.getTaskResult(taskId);
|
||||
return result;
|
||||
}
|
||||
});
|
||||
return server;
|
||||
};
|
||||
const MCP_PORT = process.env.MCP_PORT ? parseInt(process.env.MCP_PORT, 10) : 3000;
|
||||
const AUTH_PORT = process.env.MCP_AUTH_PORT ? parseInt(process.env.MCP_AUTH_PORT, 10) : 3001;
|
||||
const app = (0, express_js_1.createMcpExpressApp)();
|
||||
const app = (0, express_1.default)();
|
||||
app.use(express_1.default.json());
|
||||
// Allow CORS all domains, expose the Mcp-Session-Id header
|
||||
app.use((0, cors_1.default)({
|
||||
origin: '*', // Allow all origins
|
||||
exposedHeaders: ["Mcp-Session-Id"]
|
||||
}));
|
||||
// Set up OAuth if enabled
|
||||
let authMiddleware = null;
|
||||
if (useOAuth) {
|
||||
@@ -454,15 +382,14 @@ if (useOAuth) {
|
||||
const response = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
token: token
|
||||
}).toString()
|
||||
});
|
||||
if (!response.ok) {
|
||||
const text = await response.text().catch(() => null);
|
||||
throw new Error(`Invalid or expired token: ${text}`);
|
||||
throw new Error(`Invalid or expired token: ${await response.text()}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
if (strictOAuth) {
|
||||
@@ -478,7 +405,7 @@ if (useOAuth) {
|
||||
token,
|
||||
clientId: data.client_id,
|
||||
scopes: data.scope ? data.scope.split(' ') : [],
|
||||
expiresAt: data.exp
|
||||
expiresAt: data.exp,
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -487,12 +414,12 @@ if (useOAuth) {
|
||||
oauthMetadata,
|
||||
resourceServerUrl: mcpServerUrl,
|
||||
scopesSupported: ['mcp:tools'],
|
||||
resourceName: 'MCP Demo Server'
|
||||
resourceName: 'MCP Demo Server',
|
||||
}));
|
||||
authMiddleware = (0, bearerAuth_js_1.requireBearerAuth)({
|
||||
verifier: tokenVerifier,
|
||||
requiredScopes: [],
|
||||
resourceMetadataUrl: (0, router_js_1.getOAuthProtectedResourceMetadataUrl)(mcpServerUrl)
|
||||
resourceMetadataUrl: (0, router_js_1.getOAuthProtectedResourceMetadataUrl)(mcpServerUrl),
|
||||
});
|
||||
}
|
||||
// Map to store transports by session ID
|
||||
@@ -521,7 +448,7 @@ const mcpPostHandler = async (req, res) => {
|
||||
transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
||||
sessionIdGenerator: () => (0, node_crypto_1.randomUUID)(),
|
||||
eventStore, // Enable resumability
|
||||
onsessioninitialized: sessionId => {
|
||||
onsessioninitialized: (sessionId) => {
|
||||
// Store the transport by session ID when session is initialized
|
||||
// This avoids race conditions where requests might come in before the session is stored
|
||||
console.log(`Session initialized with ID: ${sessionId}`);
|
||||
@@ -549,9 +476,9 @@ const mcpPostHandler = async (req, res) => {
|
||||
jsonrpc: '2.0',
|
||||
error: {
|
||||
code: -32000,
|
||||
message: 'Bad Request: No valid session ID provided'
|
||||
message: 'Bad Request: No valid session ID provided',
|
||||
},
|
||||
id: null
|
||||
id: null,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -566,9 +493,9 @@ const mcpPostHandler = async (req, res) => {
|
||||
jsonrpc: '2.0',
|
||||
error: {
|
||||
code: -32603,
|
||||
message: 'Internal server error'
|
||||
message: 'Internal server error',
|
||||
},
|
||||
id: null
|
||||
id: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -634,7 +561,7 @@ if (useOAuth && authMiddleware) {
|
||||
else {
|
||||
app.delete('/mcp', mcpDeleteHandler);
|
||||
}
|
||||
app.listen(MCP_PORT, error => {
|
||||
app.listen(MCP_PORT, (error) => {
|
||||
if (error) {
|
||||
console.error('Failed to start server:', error);
|
||||
process.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user