Initial commit: Complete Hive distributed AI orchestration platform
This comprehensive implementation includes: - FastAPI backend with MCP server integration - React/TypeScript frontend with Vite - PostgreSQL database with Redis caching - Grafana/Prometheus monitoring stack - Docker Compose orchestration - Full MCP protocol support for Claude Code integration Features: - Agent discovery and management across network - Visual workflow editor and execution engine - Real-time task coordination and monitoring - Multi-model support with specialized agents - Distributed development task allocation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
163
mcp-server/README.md
Normal file
163
mcp-server/README.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# 🐝 Hive MCP Server
|
||||
|
||||
Model Context Protocol (MCP) server that exposes the Hive Distributed AI Orchestration Platform to AI assistants like Claude.
|
||||
|
||||
## Overview
|
||||
|
||||
This MCP server allows AI assistants to:
|
||||
|
||||
- 🤖 **Orchestrate Agent Tasks** - Assign development work across your distributed cluster
|
||||
- 📊 **Monitor Executions** - Track task progress and results in real-time
|
||||
- 🔄 **Manage Workflows** - Create and execute complex distributed pipelines
|
||||
- 📈 **Access Cluster Resources** - Get status, metrics, and performance data
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Install Dependencies
|
||||
|
||||
```bash
|
||||
cd mcp-server
|
||||
npm install
|
||||
```
|
||||
|
||||
### 2. Build the Server
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 3. Configure Claude Desktop
|
||||
|
||||
Add to your Claude Desktop configuration (`~/Library/Application Support/Claude/claude_desktop_config.json`):
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"hive": {
|
||||
"command": "node",
|
||||
"args": ["/path/to/hive/mcp-server/dist/index.js"],
|
||||
"env": {
|
||||
"HIVE_API_URL": "http://localhost:8087",
|
||||
"HIVE_WS_URL": "ws://localhost:8087"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Restart Claude Desktop
|
||||
|
||||
The Hive MCP server will automatically connect to your running Hive cluster.
|
||||
|
||||
## Available Tools
|
||||
|
||||
### Agent Management
|
||||
- **`hive_get_agents`** - List all registered agents with status
|
||||
- **`hive_register_agent`** - Register new agents in the cluster
|
||||
|
||||
### Task Management
|
||||
- **`hive_create_task`** - Create development tasks for specialized agents
|
||||
- **`hive_get_task`** - Get details of specific tasks
|
||||
- **`hive_get_tasks`** - List tasks with filtering options
|
||||
|
||||
### Workflow Management
|
||||
- **`hive_get_workflows`** - List available workflows
|
||||
- **`hive_create_workflow`** - Create new distributed workflows
|
||||
- **`hive_execute_workflow`** - Execute workflows with inputs
|
||||
|
||||
### Monitoring
|
||||
- **`hive_get_cluster_status`** - Get comprehensive cluster status
|
||||
- **`hive_get_metrics`** - Retrieve Prometheus metrics
|
||||
- **`hive_get_executions`** - View workflow execution history
|
||||
|
||||
### Coordination
|
||||
- **`hive_coordinate_development`** - Orchestrate complex multi-agent development projects
|
||||
|
||||
## Available Resources
|
||||
|
||||
### Real-time Cluster Data
|
||||
- **`hive://cluster/status`** - Live cluster status and health
|
||||
- **`hive://agents/list`** - Agent registry with capabilities
|
||||
- **`hive://tasks/active`** - Currently running and pending tasks
|
||||
- **`hive://tasks/completed`** - Recent task results and metrics
|
||||
|
||||
### Workflow Data
|
||||
- **`hive://workflows/available`** - All configured workflows
|
||||
- **`hive://executions/recent`** - Recent workflow executions
|
||||
|
||||
### Monitoring Data
|
||||
- **`hive://metrics/prometheus`** - Raw Prometheus metrics
|
||||
- **`hive://capabilities/overview`** - Cluster capabilities summary
|
||||
|
||||
## Example Usage with Claude
|
||||
|
||||
### Register an Agent
|
||||
```
|
||||
Please register a new agent in my Hive cluster:
|
||||
- ID: walnut-kernel-dev
|
||||
- Endpoint: http://walnut.local:11434
|
||||
- Model: codellama:34b
|
||||
- Specialization: kernel_dev
|
||||
```
|
||||
|
||||
### Create a Development Task
|
||||
```
|
||||
Create a high-priority kernel development task to optimize FlashAttention for RDNA3 GPUs.
|
||||
The task should focus on memory coalescing and include constraints for backward compatibility.
|
||||
```
|
||||
|
||||
### Coordinate Complex Development
|
||||
```
|
||||
Help me coordinate development of a new PyTorch operator that includes:
|
||||
1. CUDA/HIP kernel implementation (high priority)
|
||||
2. PyTorch integration layer (medium priority)
|
||||
3. Performance benchmarks (medium priority)
|
||||
4. Documentation and examples (low priority)
|
||||
5. Unit and integration tests (high priority)
|
||||
|
||||
Use parallel coordination where possible.
|
||||
```
|
||||
|
||||
### Monitor Cluster Status
|
||||
```
|
||||
What's the current status of my Hive cluster? Show me agent utilization and recent task performance.
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
- **`HIVE_API_URL`** - Hive backend API URL (default: `http://localhost:8087`)
|
||||
- **`HIVE_WS_URL`** - Hive WebSocket URL (default: `ws://localhost:8087`)
|
||||
|
||||
## Development
|
||||
|
||||
### Watch Mode
|
||||
```bash
|
||||
npm run watch
|
||||
```
|
||||
|
||||
### Direct Run
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Integration with Hive
|
||||
|
||||
This MCP server connects to your running Hive platform and provides a standardized interface for AI assistants to:
|
||||
|
||||
1. **Understand** your cluster capabilities and current state
|
||||
2. **Plan** complex development tasks across multiple agents
|
||||
3. **Execute** coordinated workflows with real-time monitoring
|
||||
4. **Optimize** task distribution based on agent specializations
|
||||
|
||||
The server automatically handles task queuing, agent assignment, and result aggregation - allowing AI assistants to focus on high-level orchestration and decision-making.
|
||||
|
||||
## Security Notes
|
||||
|
||||
- The MCP server connects to your local Hive cluster
|
||||
- No external network access required
|
||||
- All communication stays within your development environment
|
||||
- Agent endpoints should be on trusted networks only
|
||||
|
||||
---
|
||||
|
||||
🐝 **Ready to let Claude orchestrate your distributed AI development cluster!**
|
||||
12
mcp-server/claude_desktop_config.json
Normal file
12
mcp-server/claude_desktop_config.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"hive": {
|
||||
"command": "node",
|
||||
"args": ["/home/tony/AI/projects/hive/mcp-server/dist/index.js"],
|
||||
"env": {
|
||||
"HIVE_API_URL": "http://localhost:8087",
|
||||
"HIVE_WS_URL": "ws://localhost:8087"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
85
mcp-server/dist/hive-client.d.ts
vendored
Normal file
85
mcp-server/dist/hive-client.d.ts
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Hive Client
|
||||
*
|
||||
* Handles communication with the Hive backend API
|
||||
*/
|
||||
import WebSocket from 'ws';
|
||||
export interface HiveConfig {
|
||||
baseUrl: string;
|
||||
wsUrl: string;
|
||||
timeout: number;
|
||||
}
|
||||
export interface Agent {
|
||||
id: string;
|
||||
endpoint: string;
|
||||
model: string;
|
||||
specialty: string;
|
||||
status: 'available' | 'busy' | 'offline';
|
||||
current_tasks: number;
|
||||
max_concurrent: number;
|
||||
}
|
||||
export interface Task {
|
||||
id: string;
|
||||
type: string;
|
||||
priority: number;
|
||||
context: Record<string, any>;
|
||||
status: 'pending' | 'in_progress' | 'completed' | 'failed';
|
||||
assigned_agent?: string;
|
||||
result?: Record<string, any>;
|
||||
created_at: string;
|
||||
completed_at?: string;
|
||||
}
|
||||
export interface ClusterStatus {
|
||||
system: {
|
||||
status: string;
|
||||
uptime: number;
|
||||
version: string;
|
||||
};
|
||||
agents: {
|
||||
total: number;
|
||||
available: number;
|
||||
busy: number;
|
||||
};
|
||||
tasks: {
|
||||
total: number;
|
||||
pending: number;
|
||||
running: number;
|
||||
completed: number;
|
||||
failed: number;
|
||||
};
|
||||
}
|
||||
export declare class HiveClient {
|
||||
private api;
|
||||
private config;
|
||||
private wsConnection?;
|
||||
constructor(config?: Partial<HiveConfig>);
|
||||
testConnection(): Promise<boolean>;
|
||||
getAgents(): Promise<Agent[]>;
|
||||
registerAgent(agentData: Partial<Agent>): Promise<{
|
||||
agent_id: string;
|
||||
}>;
|
||||
createTask(taskData: {
|
||||
type: string;
|
||||
priority: number;
|
||||
context: Record<string, any>;
|
||||
}): Promise<Task>;
|
||||
getTask(taskId: string): Promise<Task>;
|
||||
getTasks(filters?: {
|
||||
status?: string;
|
||||
agent?: string;
|
||||
limit?: number;
|
||||
}): Promise<Task[]>;
|
||||
getWorkflows(): Promise<any[]>;
|
||||
createWorkflow(workflowData: Record<string, any>): Promise<{
|
||||
workflow_id: string;
|
||||
}>;
|
||||
executeWorkflow(workflowId: string, inputs?: Record<string, any>): Promise<{
|
||||
execution_id: string;
|
||||
}>;
|
||||
getClusterStatus(): Promise<ClusterStatus>;
|
||||
getMetrics(): Promise<string>;
|
||||
getExecutions(workflowId?: string): Promise<any[]>;
|
||||
connectWebSocket(topic?: string): Promise<WebSocket>;
|
||||
disconnect(): Promise<void>;
|
||||
}
|
||||
//# sourceMappingURL=hive-client.d.ts.map
|
||||
1
mcp-server/dist/hive-client.d.ts.map
vendored
Normal file
1
mcp-server/dist/hive-client.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"hive-client.d.ts","sourceRoot":"","sources":["../src/hive-client.ts"],"names":[],"mappings":"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"}
|
||||
123
mcp-server/dist/hive-client.js
vendored
Normal file
123
mcp-server/dist/hive-client.js
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* Hive Client
|
||||
*
|
||||
* Handles communication with the Hive backend API
|
||||
*/
|
||||
import axios from 'axios';
|
||||
import WebSocket from 'ws';
|
||||
export class HiveClient {
|
||||
api;
|
||||
config;
|
||||
wsConnection;
|
||||
constructor(config) {
|
||||
this.config = {
|
||||
baseUrl: process.env.HIVE_API_URL || 'http://localhost:8087',
|
||||
wsUrl: process.env.HIVE_WS_URL || 'ws://localhost:8087',
|
||||
timeout: 30000,
|
||||
...config,
|
||||
};
|
||||
this.api = axios.create({
|
||||
baseURL: this.config.baseUrl,
|
||||
timeout: this.config.timeout,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
}
|
||||
async testConnection() {
|
||||
try {
|
||||
const response = await this.api.get('/health');
|
||||
return response.data.status === 'healthy';
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error(`Failed to connect to Hive: ${error}`);
|
||||
}
|
||||
}
|
||||
// Agent Management
|
||||
async getAgents() {
|
||||
const response = await this.api.get('/api/agents');
|
||||
return response.data.agents || [];
|
||||
}
|
||||
async registerAgent(agentData) {
|
||||
const response = await this.api.post('/api/agents', agentData);
|
||||
return response.data;
|
||||
}
|
||||
// Task Management
|
||||
async createTask(taskData) {
|
||||
const response = await this.api.post('/api/tasks', taskData);
|
||||
return response.data;
|
||||
}
|
||||
async getTask(taskId) {
|
||||
const response = await this.api.get(`/api/tasks/${taskId}`);
|
||||
return response.data;
|
||||
}
|
||||
async getTasks(filters) {
|
||||
const params = new URLSearchParams();
|
||||
if (filters?.status)
|
||||
params.append('status', filters.status);
|
||||
if (filters?.agent)
|
||||
params.append('agent', filters.agent);
|
||||
if (filters?.limit)
|
||||
params.append('limit', filters.limit.toString());
|
||||
const response = await this.api.get(`/api/tasks?${params}`);
|
||||
return response.data.tasks || [];
|
||||
}
|
||||
// Workflow Management
|
||||
async getWorkflows() {
|
||||
const response = await this.api.get('/api/workflows');
|
||||
return response.data.workflows || [];
|
||||
}
|
||||
async createWorkflow(workflowData) {
|
||||
const response = await this.api.post('/api/workflows', workflowData);
|
||||
return response.data;
|
||||
}
|
||||
async executeWorkflow(workflowId, inputs) {
|
||||
const response = await this.api.post(`/api/workflows/${workflowId}/execute`, { inputs });
|
||||
return response.data;
|
||||
}
|
||||
// Monitoring and Status
|
||||
async getClusterStatus() {
|
||||
const response = await this.api.get('/api/status');
|
||||
return response.data;
|
||||
}
|
||||
async getMetrics() {
|
||||
const response = await this.api.get('/api/metrics');
|
||||
return response.data;
|
||||
}
|
||||
async getExecutions(workflowId) {
|
||||
const url = workflowId ? `/api/executions?workflow_id=${workflowId}` : '/api/executions';
|
||||
const response = await this.api.get(url);
|
||||
return response.data.executions || [];
|
||||
}
|
||||
// Real-time Updates via WebSocket
|
||||
async connectWebSocket(topic = 'general') {
|
||||
return new Promise((resolve, reject) => {
|
||||
const ws = new WebSocket(`${this.config.wsUrl}/ws/${topic}`);
|
||||
ws.on('open', () => {
|
||||
console.log(`🔗 Connected to Hive WebSocket (${topic})`);
|
||||
this.wsConnection = ws;
|
||||
resolve(ws);
|
||||
});
|
||||
ws.on('error', (error) => {
|
||||
console.error('WebSocket error:', error);
|
||||
reject(error);
|
||||
});
|
||||
ws.on('message', (data) => {
|
||||
try {
|
||||
const message = JSON.parse(data.toString());
|
||||
console.log('📨 Hive update:', message);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to parse WebSocket message:', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
async disconnect() {
|
||||
if (this.wsConnection) {
|
||||
this.wsConnection.close();
|
||||
this.wsConnection = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=hive-client.js.map
|
||||
1
mcp-server/dist/hive-client.js.map
vendored
Normal file
1
mcp-server/dist/hive-client.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"hive-client.js","sourceRoot":"","sources":["../src/hive-client.ts"],"names":[],"mappings":"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"}
|
||||
35
mcp-server/dist/hive-resources.d.ts
vendored
Normal file
35
mcp-server/dist/hive-resources.d.ts
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Hive Resources
|
||||
*
|
||||
* Defines MCP resources that expose Hive cluster state and real-time data
|
||||
*/
|
||||
import { Resource } from '@modelcontextprotocol/sdk/types.js';
|
||||
import { HiveClient } from './hive-client.js';
|
||||
export declare class HiveResources {
|
||||
private hiveClient;
|
||||
constructor(hiveClient: HiveClient);
|
||||
getAllResources(): Promise<Resource[]>;
|
||||
readResource(uri: string): Promise<{
|
||||
contents: Array<{
|
||||
type: string;
|
||||
text?: string;
|
||||
data?: string;
|
||||
mimeType?: string;
|
||||
}>;
|
||||
}>;
|
||||
private getClusterStatusResource;
|
||||
private getAgentsResource;
|
||||
private getActiveTasksResource;
|
||||
private getCompletedTasksResource;
|
||||
private getWorkflowsResource;
|
||||
private getExecutionsResource;
|
||||
private getMetricsResource;
|
||||
private getCapabilitiesResource;
|
||||
private groupAgentsBySpecialty;
|
||||
private formatTaskForResource;
|
||||
private analyzeTaskQueue;
|
||||
private calculateTaskMetrics;
|
||||
private summarizeExecutionStatuses;
|
||||
private calculateDuration;
|
||||
}
|
||||
//# sourceMappingURL=hive-resources.d.ts.map
|
||||
1
mcp-server/dist/hive-resources.d.ts.map
vendored
Normal file
1
mcp-server/dist/hive-resources.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"hive-resources.d.ts","sourceRoot":"","sources":["../src/hive-resources.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAa;gBAEnB,UAAU,EAAE,UAAU;IAI5B,eAAe,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAqDtC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;YA0ClH,wBAAwB;YAcxB,iBAAiB;YAkCjB,sBAAsB;YA0BtB,yBAAyB;YA4BzB,oBAAoB;YA0BpB,qBAAqB;YA6BrB,kBAAkB;YAclB,uBAAuB;IAyDrC,OAAO,CAAC,sBAAsB;IAW9B,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,oBAAoB;IAiB5B,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,iBAAiB;CAM1B"}
|
||||
370
mcp-server/dist/hive-resources.js
vendored
Normal file
370
mcp-server/dist/hive-resources.js
vendored
Normal file
@@ -0,0 +1,370 @@
|
||||
/**
|
||||
* Hive Resources
|
||||
*
|
||||
* Defines MCP resources that expose Hive cluster state and real-time data
|
||||
*/
|
||||
export class HiveResources {
|
||||
hiveClient;
|
||||
constructor(hiveClient) {
|
||||
this.hiveClient = hiveClient;
|
||||
}
|
||||
async getAllResources() {
|
||||
return [
|
||||
{
|
||||
uri: 'hive://cluster/status',
|
||||
name: 'Cluster Status',
|
||||
description: 'Real-time status of the entire Hive cluster including agents and tasks',
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
{
|
||||
uri: 'hive://agents/list',
|
||||
name: 'Agent Registry',
|
||||
description: 'List of all registered AI agents with their capabilities and current status',
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
{
|
||||
uri: 'hive://tasks/active',
|
||||
name: 'Active Tasks',
|
||||
description: 'Currently running and pending tasks across the cluster',
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
{
|
||||
uri: 'hive://tasks/completed',
|
||||
name: 'Completed Tasks',
|
||||
description: 'Recently completed tasks with results and performance metrics',
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
{
|
||||
uri: 'hive://workflows/available',
|
||||
name: 'Available Workflows',
|
||||
description: 'All configured workflows ready for execution',
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
{
|
||||
uri: 'hive://executions/recent',
|
||||
name: 'Recent Executions',
|
||||
description: 'Recent workflow executions with status and results',
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
{
|
||||
uri: 'hive://metrics/prometheus',
|
||||
name: 'Cluster Metrics',
|
||||
description: 'Prometheus metrics for monitoring cluster performance',
|
||||
mimeType: 'text/plain',
|
||||
},
|
||||
{
|
||||
uri: 'hive://capabilities/overview',
|
||||
name: 'Cluster Capabilities',
|
||||
description: 'Overview of available agent types and their specializations',
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
];
|
||||
}
|
||||
async readResource(uri) {
|
||||
try {
|
||||
switch (uri) {
|
||||
case 'hive://cluster/status':
|
||||
return await this.getClusterStatusResource();
|
||||
case 'hive://agents/list':
|
||||
return await this.getAgentsResource();
|
||||
case 'hive://tasks/active':
|
||||
return await this.getActiveTasksResource();
|
||||
case 'hive://tasks/completed':
|
||||
return await this.getCompletedTasksResource();
|
||||
case 'hive://workflows/available':
|
||||
return await this.getWorkflowsResource();
|
||||
case 'hive://executions/recent':
|
||||
return await this.getExecutionsResource();
|
||||
case 'hive://metrics/prometheus':
|
||||
return await this.getMetricsResource();
|
||||
case 'hive://capabilities/overview':
|
||||
return await this.getCapabilitiesResource();
|
||||
default:
|
||||
throw new Error(`Resource not found: ${uri}`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Error reading resource ${uri}: ${error instanceof Error ? error.message : String(error)}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
async getClusterStatusResource() {
|
||||
const status = await this.hiveClient.getClusterStatus();
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
type: 'text',
|
||||
data: JSON.stringify(status, null, 2),
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getAgentsResource() {
|
||||
const agents = await this.hiveClient.getAgents();
|
||||
const agentData = {
|
||||
total_agents: agents.length,
|
||||
agents: agents.map(agent => ({
|
||||
id: agent.id,
|
||||
specialty: agent.specialty,
|
||||
model: agent.model,
|
||||
endpoint: agent.endpoint,
|
||||
status: agent.status,
|
||||
current_tasks: agent.current_tasks,
|
||||
max_concurrent: agent.max_concurrent,
|
||||
utilization: agent.max_concurrent > 0 ? (agent.current_tasks / agent.max_concurrent * 100).toFixed(1) + '%' : '0%',
|
||||
})),
|
||||
by_specialty: this.groupAgentsBySpecialty(agents),
|
||||
availability_summary: {
|
||||
available: agents.filter(a => a.status === 'available').length,
|
||||
busy: agents.filter(a => a.status === 'busy').length,
|
||||
offline: agents.filter(a => a.status === 'offline').length,
|
||||
},
|
||||
};
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
type: 'text',
|
||||
data: JSON.stringify(agentData, null, 2),
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getActiveTasksResource() {
|
||||
const pendingTasks = await this.hiveClient.getTasks({ status: 'pending', limit: 50 });
|
||||
const runningTasks = await this.hiveClient.getTasks({ status: 'in_progress', limit: 50 });
|
||||
const activeData = {
|
||||
summary: {
|
||||
pending: pendingTasks.length,
|
||||
running: runningTasks.length,
|
||||
total_active: pendingTasks.length + runningTasks.length,
|
||||
},
|
||||
pending_tasks: pendingTasks.map(this.formatTaskForResource),
|
||||
running_tasks: runningTasks.map(this.formatTaskForResource),
|
||||
queue_analysis: this.analyzeTaskQueue(pendingTasks),
|
||||
};
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
type: 'text',
|
||||
data: JSON.stringify(activeData, null, 2),
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getCompletedTasksResource() {
|
||||
const completedTasks = await this.hiveClient.getTasks({ status: 'completed', limit: 20 });
|
||||
const failedTasks = await this.hiveClient.getTasks({ status: 'failed', limit: 10 });
|
||||
const completedData = {
|
||||
summary: {
|
||||
completed: completedTasks.length,
|
||||
failed: failedTasks.length,
|
||||
success_rate: completedTasks.length + failedTasks.length > 0
|
||||
? ((completedTasks.length / (completedTasks.length + failedTasks.length)) * 100).toFixed(1) + '%'
|
||||
: 'N/A',
|
||||
},
|
||||
recent_completed: completedTasks.map(this.formatTaskForResource),
|
||||
recent_failed: failedTasks.map(this.formatTaskForResource),
|
||||
performance_metrics: this.calculateTaskMetrics(completedTasks),
|
||||
};
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
type: 'text',
|
||||
data: JSON.stringify(completedData, null, 2),
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getWorkflowsResource() {
|
||||
const workflows = await this.hiveClient.getWorkflows();
|
||||
const workflowData = {
|
||||
total_workflows: workflows.length,
|
||||
workflows: workflows.map(wf => ({
|
||||
id: wf.id,
|
||||
name: wf.name || 'Unnamed Workflow',
|
||||
description: wf.description || 'No description',
|
||||
status: wf.status || 'unknown',
|
||||
created: wf.created_at || 'unknown',
|
||||
steps: wf.steps?.length || 0,
|
||||
})),
|
||||
};
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
type: 'text',
|
||||
data: JSON.stringify(workflowData, null, 2),
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getExecutionsResource() {
|
||||
const executions = await this.hiveClient.getExecutions();
|
||||
const executionData = {
|
||||
total_executions: executions.length,
|
||||
recent_executions: executions.slice(0, 10).map(exec => ({
|
||||
id: exec.id,
|
||||
workflow_id: exec.workflow_id,
|
||||
status: exec.status,
|
||||
started_at: exec.started_at,
|
||||
completed_at: exec.completed_at,
|
||||
duration: exec.completed_at && exec.started_at
|
||||
? this.calculateDuration(exec.started_at, exec.completed_at)
|
||||
: null,
|
||||
})),
|
||||
status_summary: this.summarizeExecutionStatuses(executions),
|
||||
};
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
type: 'text',
|
||||
data: JSON.stringify(executionData, null, 2),
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getMetricsResource() {
|
||||
const metrics = await this.hiveClient.getMetrics();
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
type: 'text',
|
||||
text: metrics,
|
||||
mimeType: 'text/plain',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getCapabilitiesResource() {
|
||||
const agents = await this.hiveClient.getAgents();
|
||||
const capabilities = {
|
||||
agent_specializations: {
|
||||
kernel_dev: {
|
||||
description: 'GPU kernel development, HIP/CUDA optimization, memory coalescing',
|
||||
available_agents: agents.filter(a => a.specialty === 'kernel_dev').length,
|
||||
typical_models: ['codellama:34b', 'deepseek-coder:33b'],
|
||||
},
|
||||
pytorch_dev: {
|
||||
description: 'PyTorch backend development, autograd, TunableOp integration',
|
||||
available_agents: agents.filter(a => a.specialty === 'pytorch_dev').length,
|
||||
typical_models: ['deepseek-coder:33b', 'codellama:34b'],
|
||||
},
|
||||
profiler: {
|
||||
description: 'Performance analysis, GPU profiling, bottleneck identification',
|
||||
available_agents: agents.filter(a => a.specialty === 'profiler').length,
|
||||
typical_models: ['llama3:70b', 'mixtral:8x7b'],
|
||||
},
|
||||
docs_writer: {
|
||||
description: 'Technical documentation, API docs, tutorials, examples',
|
||||
available_agents: agents.filter(a => a.specialty === 'docs_writer').length,
|
||||
typical_models: ['llama3:70b', 'claude-3-haiku'],
|
||||
},
|
||||
tester: {
|
||||
description: 'Test creation, benchmarking, CI/CD, edge case handling',
|
||||
available_agents: agents.filter(a => a.specialty === 'tester').length,
|
||||
typical_models: ['codellama:34b', 'deepseek-coder:33b'],
|
||||
},
|
||||
},
|
||||
cluster_capacity: {
|
||||
total_agents: agents.length,
|
||||
total_concurrent_capacity: agents.reduce((sum, agent) => sum + agent.max_concurrent, 0),
|
||||
current_utilization: agents.reduce((sum, agent) => sum + agent.current_tasks, 0),
|
||||
},
|
||||
supported_frameworks: [
|
||||
'ROCm/HIP', 'PyTorch', 'CUDA', 'OpenMP', 'MPI', 'Composable Kernel'
|
||||
],
|
||||
target_architectures: [
|
||||
'RDNA3', 'CDNA3', 'RDNA2', 'Vega', 'NVIDIA GPUs (via CUDA)'
|
||||
],
|
||||
};
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
type: 'text',
|
||||
data: JSON.stringify(capabilities, null, 2),
|
||||
mimeType: 'application/json',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
// Helper Methods
|
||||
groupAgentsBySpecialty(agents) {
|
||||
const grouped = {};
|
||||
agents.forEach(agent => {
|
||||
if (!grouped[agent.specialty]) {
|
||||
grouped[agent.specialty] = [];
|
||||
}
|
||||
grouped[agent.specialty].push(agent);
|
||||
});
|
||||
return grouped;
|
||||
}
|
||||
formatTaskForResource(task) {
|
||||
return {
|
||||
id: task.id,
|
||||
type: task.type,
|
||||
priority: task.priority,
|
||||
status: task.status,
|
||||
assigned_agent: task.assigned_agent,
|
||||
created_at: task.created_at,
|
||||
completed_at: task.completed_at,
|
||||
objective: task.context?.objective || 'No objective specified',
|
||||
};
|
||||
}
|
||||
analyzeTaskQueue(tasks) {
|
||||
const byType = tasks.reduce((acc, task) => {
|
||||
acc[task.type] = (acc[task.type] || 0) + 1;
|
||||
return acc;
|
||||
}, {});
|
||||
const byPriority = tasks.reduce((acc, task) => {
|
||||
const priority = `priority_${task.priority}`;
|
||||
acc[priority] = (acc[priority] || 0) + 1;
|
||||
return acc;
|
||||
}, {});
|
||||
return {
|
||||
by_type: byType,
|
||||
by_priority: byPriority,
|
||||
average_priority: tasks.length > 0
|
||||
? (tasks.reduce((sum, task) => sum + task.priority, 0) / tasks.length).toFixed(1)
|
||||
: 0,
|
||||
};
|
||||
}
|
||||
calculateTaskMetrics(tasks) {
|
||||
if (tasks.length === 0)
|
||||
return null;
|
||||
const durations = tasks
|
||||
.filter(task => task.created_at && task.completed_at)
|
||||
.map(task => new Date(task.completed_at).getTime() - new Date(task.created_at).getTime());
|
||||
if (durations.length === 0)
|
||||
return null;
|
||||
return {
|
||||
average_duration_ms: Math.round(durations.reduce((a, b) => a + b, 0) / durations.length),
|
||||
min_duration_ms: Math.min(...durations),
|
||||
max_duration_ms: Math.max(...durations),
|
||||
total_tasks_analyzed: durations.length,
|
||||
};
|
||||
}
|
||||
summarizeExecutionStatuses(executions) {
|
||||
return executions.reduce((acc, exec) => {
|
||||
acc[exec.status] = (acc[exec.status] || 0) + 1;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
calculateDuration(start, end) {
|
||||
const duration = new Date(end).getTime() - new Date(start).getTime();
|
||||
const minutes = Math.floor(duration / 60000);
|
||||
const seconds = Math.floor((duration % 60000) / 1000);
|
||||
return `${minutes}m ${seconds}s`;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=hive-resources.js.map
|
||||
1
mcp-server/dist/hive-resources.js.map
vendored
Normal file
1
mcp-server/dist/hive-resources.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
27
mcp-server/dist/hive-tools.d.ts
vendored
Normal file
27
mcp-server/dist/hive-tools.d.ts
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Hive Tools
|
||||
*
|
||||
* Defines MCP tools that expose Hive operations to AI assistants
|
||||
*/
|
||||
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
||||
import { HiveClient } from './hive-client.js';
|
||||
export declare class HiveTools {
|
||||
private hiveClient;
|
||||
constructor(hiveClient: HiveClient);
|
||||
getAllTools(): Tool[];
|
||||
executeTool(name: string, args: Record<string, any>): Promise<any>;
|
||||
private getAgents;
|
||||
private registerAgent;
|
||||
private createTask;
|
||||
private getTask;
|
||||
private getTasks;
|
||||
private getWorkflows;
|
||||
private createWorkflow;
|
||||
private executeWorkflow;
|
||||
private getClusterStatus;
|
||||
private getMetrics;
|
||||
private getExecutions;
|
||||
private coordinateDevelopment;
|
||||
private bringHiveOnline;
|
||||
}
|
||||
//# sourceMappingURL=hive-tools.d.ts.map
|
||||
1
mcp-server/dist/hive-tools.d.ts.map
vendored
Normal file
1
mcp-server/dist/hive-tools.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"hive-tools.d.ts","sourceRoot":"","sources":["../src/hive-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAe,MAAM,kBAAkB,CAAC;AAM3D,qBAAa,SAAS;IACpB,OAAO,CAAC,UAAU,CAAa;gBAEnB,UAAU,EAAE,UAAU;IAIlC,WAAW,IAAI,IAAI,EAAE;IAmOf,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;YAkE1D,SAAS;YAqBT,aAAa;YAkBb,UAAU;YA6BV,OAAO;YAoBP,QAAQ;YAsBR,YAAY;YAqBZ,cAAc;YAiBd,eAAe;YAiBf,gBAAgB;YAuBhB,UAAU;YAaV,aAAa;YAsBb,qBAAqB;YAuCrB,eAAe;CAyF9B"}
|
||||
590
mcp-server/dist/hive-tools.js
vendored
Normal file
590
mcp-server/dist/hive-tools.js
vendored
Normal file
@@ -0,0 +1,590 @@
|
||||
/**
|
||||
* Hive Tools
|
||||
*
|
||||
* Defines MCP tools that expose Hive operations to AI assistants
|
||||
*/
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { spawn } from 'child_process';
|
||||
import * as path from 'path';
|
||||
export class HiveTools {
|
||||
hiveClient;
|
||||
constructor(hiveClient) {
|
||||
this.hiveClient = hiveClient;
|
||||
}
|
||||
getAllTools() {
|
||||
return [
|
||||
// Agent Management Tools
|
||||
{
|
||||
name: 'hive_get_agents',
|
||||
description: 'Get all registered AI agents in the Hive cluster with their current status',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'hive_register_agent',
|
||||
description: 'Register a new AI agent in the Hive cluster',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique agent identifier' },
|
||||
endpoint: { type: 'string', description: 'Agent API endpoint URL' },
|
||||
model: { type: 'string', description: 'Model name (e.g., codellama:34b)' },
|
||||
specialty: {
|
||||
type: 'string',
|
||||
enum: ['kernel_dev', 'pytorch_dev', 'profiler', 'docs_writer', 'tester'],
|
||||
description: 'Agent specialization area'
|
||||
},
|
||||
max_concurrent: { type: 'number', description: 'Maximum concurrent tasks', default: 2 },
|
||||
},
|
||||
required: ['id', 'endpoint', 'model', 'specialty'],
|
||||
},
|
||||
},
|
||||
// Task Management Tools
|
||||
{
|
||||
name: 'hive_create_task',
|
||||
description: 'Create and assign a development task to the Hive cluster',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
type: {
|
||||
type: 'string',
|
||||
enum: ['kernel_dev', 'pytorch_dev', 'profiler', 'docs_writer', 'tester'],
|
||||
description: 'Type of development task'
|
||||
},
|
||||
priority: {
|
||||
type: 'number',
|
||||
minimum: 1,
|
||||
maximum: 5,
|
||||
description: 'Task priority (1=low, 5=high)'
|
||||
},
|
||||
objective: { type: 'string', description: 'Main objective or goal of the task' },
|
||||
context: {
|
||||
type: 'object',
|
||||
description: 'Additional context, files, constraints, requirements',
|
||||
properties: {
|
||||
files: { type: 'array', items: { type: 'string' }, description: 'Related file paths' },
|
||||
constraints: { type: 'array', items: { type: 'string' }, description: 'Development constraints' },
|
||||
requirements: { type: 'array', items: { type: 'string' }, description: 'Specific requirements' },
|
||||
reference: { type: 'string', description: 'Reference documentation or links' }
|
||||
}
|
||||
},
|
||||
},
|
||||
required: ['type', 'priority', 'objective'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'hive_get_task',
|
||||
description: 'Get details and status of a specific task',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
task_id: { type: 'string', description: 'Task identifier' },
|
||||
},
|
||||
required: ['task_id'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'hive_get_tasks',
|
||||
description: 'Get list of tasks with optional filtering',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
status: {
|
||||
type: 'string',
|
||||
enum: ['pending', 'in_progress', 'completed', 'failed'],
|
||||
description: 'Filter by task status'
|
||||
},
|
||||
agent: { type: 'string', description: 'Filter by assigned agent ID' },
|
||||
limit: { type: 'number', description: 'Maximum number of tasks to return', default: 20 },
|
||||
},
|
||||
},
|
||||
},
|
||||
// Workflow Management Tools
|
||||
{
|
||||
name: 'hive_get_workflows',
|
||||
description: 'Get all available workflows in the Hive platform',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'hive_create_workflow',
|
||||
description: 'Create a new workflow for distributed task orchestration',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'Workflow name' },
|
||||
description: { type: 'string', description: 'Workflow description' },
|
||||
steps: {
|
||||
type: 'array',
|
||||
description: 'Workflow steps in order',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string' },
|
||||
type: { type: 'string' },
|
||||
agent_type: { type: 'string' },
|
||||
inputs: { type: 'object' },
|
||||
outputs: { type: 'array', items: { type: 'string' } }
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
required: ['name', 'steps'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'hive_execute_workflow',
|
||||
description: 'Execute a workflow with optional input parameters',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
workflow_id: { type: 'string', description: 'Workflow identifier' },
|
||||
inputs: {
|
||||
type: 'object',
|
||||
description: 'Input parameters for workflow execution',
|
||||
additionalProperties: true
|
||||
},
|
||||
},
|
||||
required: ['workflow_id'],
|
||||
},
|
||||
},
|
||||
// Monitoring and Status Tools
|
||||
{
|
||||
name: 'hive_get_cluster_status',
|
||||
description: 'Get comprehensive status of the entire Hive cluster',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'hive_get_metrics',
|
||||
description: 'Get Prometheus metrics from the Hive cluster',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'hive_get_executions',
|
||||
description: 'Get workflow execution history and status',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
workflow_id: { type: 'string', description: 'Filter by specific workflow ID' },
|
||||
},
|
||||
},
|
||||
},
|
||||
// Coordination Tools
|
||||
{
|
||||
name: 'hive_coordinate_development',
|
||||
description: 'Coordinate a complex development task across multiple specialized agents',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
project_description: { type: 'string', description: 'Overall project or feature description' },
|
||||
breakdown: {
|
||||
type: 'array',
|
||||
description: 'Task breakdown by specialization',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
specialization: { type: 'string', enum: ['kernel_dev', 'pytorch_dev', 'profiler', 'docs_writer', 'tester'] },
|
||||
task_description: { type: 'string' },
|
||||
dependencies: { type: 'array', items: { type: 'string' } },
|
||||
priority: { type: 'number', minimum: 1, maximum: 5 }
|
||||
}
|
||||
}
|
||||
},
|
||||
coordination_strategy: {
|
||||
type: 'string',
|
||||
enum: ['sequential', 'parallel', 'mixed'],
|
||||
description: 'How to coordinate the tasks',
|
||||
default: 'mixed'
|
||||
},
|
||||
},
|
||||
required: ['project_description', 'breakdown'],
|
||||
},
|
||||
},
|
||||
// Cluster Management Tools
|
||||
{
|
||||
name: 'hive_bring_online',
|
||||
description: 'Automatically discover and register all available Ollama agents on the network, bringing the entire Hive cluster online',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
force_refresh: {
|
||||
type: 'boolean',
|
||||
description: 'Force refresh of all agents (re-register existing ones)',
|
||||
default: false
|
||||
},
|
||||
subnet_scan: {
|
||||
type: 'boolean',
|
||||
description: 'Perform full subnet scan for discovery',
|
||||
default: true
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
async executeTool(name, args) {
|
||||
try {
|
||||
switch (name) {
|
||||
// Agent Management
|
||||
case 'hive_get_agents':
|
||||
return await this.getAgents();
|
||||
case 'hive_register_agent':
|
||||
return await this.registerAgent(args);
|
||||
// Task Management
|
||||
case 'hive_create_task':
|
||||
return await this.createTask(args);
|
||||
case 'hive_get_task':
|
||||
return await this.getTask(args.task_id);
|
||||
case 'hive_get_tasks':
|
||||
return await this.getTasks(args);
|
||||
// Workflow Management
|
||||
case 'hive_get_workflows':
|
||||
return await this.getWorkflows();
|
||||
case 'hive_create_workflow':
|
||||
return await this.createWorkflow(args);
|
||||
case 'hive_execute_workflow':
|
||||
return await this.executeWorkflow(args.workflow_id, args.inputs);
|
||||
// Monitoring
|
||||
case 'hive_get_cluster_status':
|
||||
return await this.getClusterStatus();
|
||||
case 'hive_get_metrics':
|
||||
return await this.getMetrics();
|
||||
case 'hive_get_executions':
|
||||
return await this.getExecutions(args.workflow_id);
|
||||
// Coordination
|
||||
case 'hive_coordinate_development':
|
||||
return await this.coordinateDevelopment(args);
|
||||
// Cluster Management
|
||||
case 'hive_bring_online':
|
||||
return await this.bringHiveOnline(args);
|
||||
default:
|
||||
throw new Error(`Unknown tool: ${name}`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Error executing ${name}: ${error instanceof Error ? error.message : String(error)}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
// Tool Implementation Methods
|
||||
async getAgents() {
|
||||
const agents = await this.hiveClient.getAgents();
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `📋 Hive Cluster Agents (${agents.length} total):\n\n${agents.length > 0
|
||||
? agents.map(agent => `🤖 **${agent.id}** (${agent.specialty})\n` +
|
||||
` • Model: ${agent.model}\n` +
|
||||
` • Endpoint: ${agent.endpoint}\n` +
|
||||
` • Status: ${agent.status}\n` +
|
||||
` • Tasks: ${agent.current_tasks}/${agent.max_concurrent}\n`).join('\n')
|
||||
: 'No agents registered yet. Use hive_register_agent to add agents to the cluster.'}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async registerAgent(args) {
|
||||
const result = await this.hiveClient.registerAgent(args);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `✅ Successfully registered agent **${args.id}** in the Hive cluster!\n\n` +
|
||||
`🤖 Agent Details:\n` +
|
||||
`• ID: ${args.id}\n` +
|
||||
`• Specialization: ${args.specialty}\n` +
|
||||
`• Model: ${args.model}\n` +
|
||||
`• Endpoint: ${args.endpoint}\n` +
|
||||
`• Max Concurrent Tasks: ${args.max_concurrent || 2}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async createTask(args) {
|
||||
const taskData = {
|
||||
type: args.type,
|
||||
priority: args.priority,
|
||||
context: {
|
||||
objective: args.objective,
|
||||
...args.context,
|
||||
},
|
||||
};
|
||||
const task = await this.hiveClient.createTask(taskData);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `🎯 Created development task **${task.id}**\n\n` +
|
||||
`📋 Task Details:\n` +
|
||||
`• Type: ${task.type}\n` +
|
||||
`• Priority: ${task.priority}/5\n` +
|
||||
`• Status: ${task.status}\n` +
|
||||
`• Objective: ${args.objective}\n` +
|
||||
`• Created: ${task.created_at}\n\n` +
|
||||
`The task has been queued and will be assigned to an available ${task.type} agent.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getTask(taskId) {
|
||||
const task = await this.hiveClient.getTask(taskId);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `🎯 Task **${task.id}** Details:\n\n` +
|
||||
`• Type: ${task.type}\n` +
|
||||
`• Priority: ${task.priority}/5\n` +
|
||||
`• Status: ${task.status}\n` +
|
||||
`• Assigned Agent: ${task.assigned_agent || 'Not assigned yet'}\n` +
|
||||
`• Created: ${task.created_at}\n` +
|
||||
`${task.completed_at ? `• Completed: ${task.completed_at}\n` : ''}` +
|
||||
`${task.result ? `\n📊 Result:\n${JSON.stringify(task.result, null, 2)}` : ''}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getTasks(args) {
|
||||
const tasks = await this.hiveClient.getTasks(args);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `📋 Hive Tasks (${tasks.length} found):\n\n${tasks.length > 0
|
||||
? tasks.map(task => `🎯 **${task.id}** (${task.type})\n` +
|
||||
` • Status: ${task.status}\n` +
|
||||
` • Priority: ${task.priority}/5\n` +
|
||||
` • Agent: ${task.assigned_agent || 'Unassigned'}\n` +
|
||||
` • Created: ${task.created_at}\n`).join('\n')
|
||||
: 'No tasks found matching the criteria.'}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getWorkflows() {
|
||||
const workflows = await this.hiveClient.getWorkflows();
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `🔄 Hive Workflows (${workflows.length} total):\n\n${workflows.length > 0
|
||||
? workflows.map(wf => `🔄 **${wf.name || wf.id}**\n` +
|
||||
` • ID: ${wf.id}\n` +
|
||||
` • Description: ${wf.description || 'No description'}\n` +
|
||||
` • Status: ${wf.status || 'Unknown'}\n`).join('\n')
|
||||
: 'No workflows created yet. Use hive_create_workflow to create distributed workflows.'}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async createWorkflow(args) {
|
||||
const result = await this.hiveClient.createWorkflow(args);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `✅ Created workflow **${args.name}**!\n\n` +
|
||||
`🔄 Workflow ID: ${result.workflow_id}\n` +
|
||||
`📋 Description: ${args.description || 'No description provided'}\n` +
|
||||
`🔧 Steps: ${args.steps.length} configured\n\n` +
|
||||
`The workflow is ready for execution using hive_execute_workflow.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async executeWorkflow(workflowId, inputs) {
|
||||
const result = await this.hiveClient.executeWorkflow(workflowId, inputs);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `🚀 Started workflow execution!\n\n` +
|
||||
`🔄 Workflow ID: ${workflowId}\n` +
|
||||
`⚡ Execution ID: ${result.execution_id}\n` +
|
||||
`📥 Inputs: ${inputs ? JSON.stringify(inputs, null, 2) : 'None'}\n\n` +
|
||||
`Use hive_get_executions to monitor progress.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getClusterStatus() {
|
||||
const status = await this.hiveClient.getClusterStatus();
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `🐝 **Hive Cluster Status**\n\n` +
|
||||
`🟢 **System**: ${status.system.status} (v${status.system.version})\n` +
|
||||
`⏱️ **Uptime**: ${Math.floor(status.system.uptime / 3600)}h ${Math.floor((status.system.uptime % 3600) / 60)}m\n\n` +
|
||||
`🤖 **Agents**: ${status.agents.total} total\n` +
|
||||
` • Available: ${status.agents.available}\n` +
|
||||
` • Busy: ${status.agents.busy}\n\n` +
|
||||
`🎯 **Tasks**: ${status.tasks.total} total\n` +
|
||||
` • Pending: ${status.tasks.pending}\n` +
|
||||
` • Running: ${status.tasks.running}\n` +
|
||||
` • Completed: ${status.tasks.completed}\n` +
|
||||
` • Failed: ${status.tasks.failed}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getMetrics() {
|
||||
const metrics = await this.hiveClient.getMetrics();
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `📊 **Hive Cluster Metrics**\n\n\`\`\`\n${metrics}\n\`\`\``,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async getExecutions(workflowId) {
|
||||
const executions = await this.hiveClient.getExecutions(workflowId);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `⚡ Workflow Executions (${executions.length} found):\n\n${executions.length > 0
|
||||
? executions.map(exec => `⚡ **${exec.id}**\n` +
|
||||
` • Workflow: ${exec.workflow_id}\n` +
|
||||
` • Status: ${exec.status}\n` +
|
||||
` • Started: ${exec.started_at}\n` +
|
||||
`${exec.completed_at ? ` • Completed: ${exec.completed_at}\n` : ''}`).join('\n')
|
||||
: 'No executions found.'}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async coordinateDevelopment(args) {
|
||||
const { project_description, breakdown, coordination_strategy = 'mixed' } = args;
|
||||
// Create tasks for each specialization in the breakdown
|
||||
const createdTasks = [];
|
||||
for (const item of breakdown) {
|
||||
const taskData = {
|
||||
type: item.specialization,
|
||||
priority: item.priority,
|
||||
context: {
|
||||
objective: item.task_description,
|
||||
project_context: project_description,
|
||||
dependencies: item.dependencies || [],
|
||||
coordination_id: uuidv4(),
|
||||
},
|
||||
};
|
||||
const task = await this.hiveClient.createTask(taskData);
|
||||
createdTasks.push(task);
|
||||
}
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `🎯 **Development Coordination Initiated**\n\n` +
|
||||
`📋 **Project**: ${project_description}\n` +
|
||||
`🔄 **Strategy**: ${coordination_strategy}\n` +
|
||||
`🎯 **Tasks Created**: ${createdTasks.length}\n\n` +
|
||||
`**Task Breakdown:**\n${createdTasks.map(task => `• **${task.id}** (${task.type}) - Priority ${task.priority}/5`).join('\n')}\n\n` +
|
||||
`All tasks have been queued and will be distributed to specialized agents based on availability and dependencies.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
async bringHiveOnline(args) {
|
||||
const { force_refresh = false, subnet_scan = true } = args;
|
||||
try {
|
||||
// Get the path to the auto-discovery script
|
||||
const scriptPath = path.resolve('/home/tony/AI/projects/hive/scripts/auto_discover_agents.py');
|
||||
return new Promise((resolve, reject) => {
|
||||
let output = '';
|
||||
let errorOutput = '';
|
||||
// Execute the auto-discovery script
|
||||
const child = spawn('python3', [scriptPath], {
|
||||
cwd: '/home/tony/AI/projects/hive',
|
||||
stdio: 'pipe',
|
||||
});
|
||||
child.stdout.on('data', (data) => {
|
||||
output += data.toString();
|
||||
});
|
||||
child.stderr.on('data', (data) => {
|
||||
errorOutput += data.toString();
|
||||
});
|
||||
child.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
// Parse the output to extract key information
|
||||
const lines = output.split('\n');
|
||||
const discoveredMatch = lines.find(l => l.includes('Discovered:'));
|
||||
const registeredMatch = lines.find(l => l.includes('Registered:'));
|
||||
const failedMatch = lines.find(l => l.includes('Failed:'));
|
||||
const discovered = discoveredMatch ? discoveredMatch.split('Discovered: ')[1]?.split(' ')[0] : '0';
|
||||
const registered = registeredMatch ? registeredMatch.split('Registered: ')[1]?.split(' ')[0] : '0';
|
||||
const failed = failedMatch ? failedMatch.split('Failed: ')[1]?.split(' ')[0] : '0';
|
||||
// Extract agent details from output
|
||||
const agentLines = lines.filter(l => l.includes('•') && l.includes('models'));
|
||||
const agentDetails = agentLines.map(line => {
|
||||
const match = line.match(/• (.+) \((.+)\) - (\d+) models/);
|
||||
return match ? `• **${match[1]}** (${match[2]}) - ${match[3]} models` : line;
|
||||
});
|
||||
resolve({
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `🐝 **Hive Cluster Online!** 🚀\n\n` +
|
||||
`🔍 **Auto-Discovery Complete**\n` +
|
||||
`• Discovered: ${discovered} agents\n` +
|
||||
`• Registered: ${registered} agents\n` +
|
||||
`• Failed: ${failed} agents\n\n` +
|
||||
`🤖 **Active Agents:**\n${agentDetails.join('\n')}\n\n` +
|
||||
`✅ **Status**: The Hive cluster is now fully operational and ready for distributed AI orchestration!\n\n` +
|
||||
`🎯 **Next Steps:**\n` +
|
||||
`• Use \`hive_get_cluster_status\` to view detailed status\n` +
|
||||
`• Use \`hive_coordinate_development\` to start distributed tasks\n` +
|
||||
`• Use \`hive_create_workflow\` to build complex workflows`,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
else {
|
||||
reject(new Error(`Auto-discovery script failed with exit code ${code}. Error: ${errorOutput}`));
|
||||
}
|
||||
});
|
||||
child.on('error', (error) => {
|
||||
reject(new Error(`Failed to execute auto-discovery script: ${error.message}`));
|
||||
});
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `❌ **Failed to bring Hive online**\n\n` +
|
||||
`Error: ${error instanceof Error ? error.message : String(error)}\n\n` +
|
||||
`Please ensure:\n` +
|
||||
`• The Hive backend is running\n` +
|
||||
`• The auto-discovery script exists at /home/tony/AI/projects/hive/scripts/auto_discover_agents.py\n` +
|
||||
`• Python3 is available and required dependencies are installed`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=hive-tools.js.map
|
||||
1
mcp-server/dist/hive-tools.js.map
vendored
Normal file
1
mcp-server/dist/hive-tools.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
9
mcp-server/dist/index.d.ts
vendored
Normal file
9
mcp-server/dist/index.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Hive MCP Server
|
||||
*
|
||||
* Exposes the Hive Distributed AI Orchestration Platform via Model Context Protocol (MCP)
|
||||
* Allows AI assistants like Claude to directly orchestrate distributed development tasks
|
||||
*/
|
||||
export {};
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
mcp-server/dist/index.d.ts.map
vendored
Normal file
1
mcp-server/dist/index.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG"}
|
||||
107
mcp-server/dist/index.js
vendored
Normal file
107
mcp-server/dist/index.js
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Hive MCP Server
|
||||
*
|
||||
* Exposes the Hive Distributed AI Orchestration Platform via Model Context Protocol (MCP)
|
||||
* Allows AI assistants like Claude to directly orchestrate distributed development tasks
|
||||
*/
|
||||
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
||||
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
||||
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
||||
import { HiveClient } from './hive-client.js';
|
||||
import { HiveTools } from './hive-tools.js';
|
||||
import { HiveResources } from './hive-resources.js';
|
||||
class HiveMCPServer {
|
||||
server;
|
||||
hiveClient;
|
||||
hiveTools;
|
||||
hiveResources;
|
||||
constructor() {
|
||||
this.server = new Server({
|
||||
name: 'hive-mcp-server',
|
||||
version: '1.0.0',
|
||||
}, {
|
||||
capabilities: {
|
||||
tools: {},
|
||||
resources: {},
|
||||
},
|
||||
});
|
||||
// Initialize Hive client and handlers
|
||||
this.hiveClient = new HiveClient();
|
||||
this.hiveTools = new HiveTools(this.hiveClient);
|
||||
this.hiveResources = new HiveResources(this.hiveClient);
|
||||
this.setupHandlers();
|
||||
}
|
||||
setupHandlers() {
|
||||
// Tools handler - exposes Hive operations as MCP tools
|
||||
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
return {
|
||||
tools: this.hiveTools.getAllTools(),
|
||||
};
|
||||
});
|
||||
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
const { name, arguments: args } = request.params;
|
||||
return await this.hiveTools.executeTool(name, args || {});
|
||||
});
|
||||
// Resources handler - exposes Hive cluster state as MCP resources
|
||||
this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
||||
return {
|
||||
resources: await this.hiveResources.getAllResources(),
|
||||
};
|
||||
});
|
||||
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
||||
const { uri } = request.params;
|
||||
return await this.hiveResources.readResource(uri);
|
||||
});
|
||||
// Error handling
|
||||
this.server.onerror = (error) => {
|
||||
console.error('[MCP Server Error]:', error);
|
||||
};
|
||||
process.on('SIGINT', async () => {
|
||||
await this.server.close();
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
async start() {
|
||||
console.log('🐝 Starting Hive MCP Server...');
|
||||
// Test connection to Hive backend
|
||||
try {
|
||||
await this.hiveClient.testConnection();
|
||||
console.log('✅ Connected to Hive backend successfully');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('❌ Failed to connect to Hive backend:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
// Auto-discover and register agents on startup
|
||||
console.log('🔍 Auto-discovering agents...');
|
||||
try {
|
||||
await this.autoDiscoverAgents();
|
||||
console.log('✅ Auto-discovery completed successfully');
|
||||
}
|
||||
catch (error) {
|
||||
console.warn('⚠️ Auto-discovery failed, continuing without it:', error);
|
||||
}
|
||||
const transport = new StdioServerTransport();
|
||||
await this.server.connect(transport);
|
||||
console.log('🚀 Hive MCP Server running on stdio');
|
||||
console.log('🔗 AI assistants can now orchestrate your distributed cluster!');
|
||||
}
|
||||
async autoDiscoverAgents() {
|
||||
// Use the existing hive_bring_online functionality
|
||||
const result = await this.hiveTools.executeTool('hive_bring_online', {
|
||||
force_refresh: false,
|
||||
subnet_scan: true
|
||||
});
|
||||
if (result.isError) {
|
||||
throw new Error(`Auto-discovery failed: ${result.content[0]?.text || 'Unknown error'}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Start the server
|
||||
const server = new HiveMCPServer();
|
||||
server.start().catch((error) => {
|
||||
console.error('Failed to start Hive MCP Server:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
mcp-server/dist/index.js.map
vendored
Normal file
1
mcp-server/dist/index.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
||||
1
mcp-server/node_modules/.bin/node-which
generated
vendored
Symbolic link
1
mcp-server/node_modules/.bin/node-which
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../which/bin/node-which
|
||||
1
mcp-server/node_modules/.bin/tsc
generated
vendored
Symbolic link
1
mcp-server/node_modules/.bin/tsc
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../typescript/bin/tsc
|
||||
1
mcp-server/node_modules/.bin/tsserver
generated
vendored
Symbolic link
1
mcp-server/node_modules/.bin/tsserver
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../typescript/bin/tsserver
|
||||
1
mcp-server/node_modules/.bin/uuid
generated
vendored
Symbolic link
1
mcp-server/node_modules/.bin/uuid
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../uuid/dist/bin/uuid
|
||||
1255
mcp-server/node_modules/.package-lock.json
generated
vendored
Normal file
1255
mcp-server/node_modules/.package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
21
mcp-server/node_modules/@modelcontextprotocol/sdk/LICENSE
generated
vendored
Normal file
21
mcp-server/node_modules/@modelcontextprotocol/sdk/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Anthropic, PBC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
1276
mcp-server/node_modules/@modelcontextprotocol/sdk/README.md
generated
vendored
Normal file
1276
mcp-server/node_modules/@modelcontextprotocol/sdk/README.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/cli.d.ts
generated
vendored
Normal file
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/cli.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=cli.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/cli.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/cli.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
|
||||
131
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/cli.js
generated
vendored
Normal file
131
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/cli.js
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const ws_1 = __importDefault(require("ws"));
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
global.WebSocket = ws_1.default;
|
||||
const express_1 = __importDefault(require("express"));
|
||||
const index_js_1 = require("./client/index.js");
|
||||
const sse_js_1 = require("./client/sse.js");
|
||||
const stdio_js_1 = require("./client/stdio.js");
|
||||
const websocket_js_1 = require("./client/websocket.js");
|
||||
const index_js_2 = require("./server/index.js");
|
||||
const sse_js_2 = require("./server/sse.js");
|
||||
const stdio_js_2 = require("./server/stdio.js");
|
||||
const types_js_1 = require("./types.js");
|
||||
async function runClient(url_or_command, args) {
|
||||
const client = new index_js_1.Client({
|
||||
name: "mcp-typescript test client",
|
||||
version: "0.1.0",
|
||||
}, {
|
||||
capabilities: {
|
||||
sampling: {},
|
||||
},
|
||||
});
|
||||
let clientTransport;
|
||||
let url = undefined;
|
||||
try {
|
||||
url = new URL(url_or_command);
|
||||
}
|
||||
catch (_a) {
|
||||
// Ignore
|
||||
}
|
||||
if ((url === null || url === void 0 ? void 0 : url.protocol) === "http:" || (url === null || url === void 0 ? void 0 : url.protocol) === "https:") {
|
||||
clientTransport = new sse_js_1.SSEClientTransport(new URL(url_or_command));
|
||||
}
|
||||
else if ((url === null || url === void 0 ? void 0 : url.protocol) === "ws:" || (url === null || url === void 0 ? void 0 : url.protocol) === "wss:") {
|
||||
clientTransport = new websocket_js_1.WebSocketClientTransport(new URL(url_or_command));
|
||||
}
|
||||
else {
|
||||
clientTransport = new stdio_js_1.StdioClientTransport({
|
||||
command: url_or_command,
|
||||
args,
|
||||
});
|
||||
}
|
||||
console.log("Connected to server.");
|
||||
await client.connect(clientTransport);
|
||||
console.log("Initialized.");
|
||||
await client.request({ method: "resources/list" }, types_js_1.ListResourcesResultSchema);
|
||||
await client.close();
|
||||
console.log("Closed.");
|
||||
}
|
||||
async function runServer(port) {
|
||||
if (port !== null) {
|
||||
const app = (0, express_1.default)();
|
||||
let servers = [];
|
||||
app.get("/sse", async (req, res) => {
|
||||
console.log("Got new SSE connection");
|
||||
const transport = new sse_js_2.SSEServerTransport("/message", res);
|
||||
const server = new index_js_2.Server({
|
||||
name: "mcp-typescript test server",
|
||||
version: "0.1.0",
|
||||
}, {
|
||||
capabilities: {},
|
||||
});
|
||||
servers.push(server);
|
||||
server.onclose = () => {
|
||||
console.log("SSE connection closed");
|
||||
servers = servers.filter((s) => s !== server);
|
||||
};
|
||||
await server.connect(transport);
|
||||
});
|
||||
app.post("/message", async (req, res) => {
|
||||
console.log("Received message");
|
||||
const sessionId = req.query.sessionId;
|
||||
const transport = servers
|
||||
.map((s) => s.transport)
|
||||
.find((t) => t.sessionId === sessionId);
|
||||
if (!transport) {
|
||||
res.status(404).send("Session not found");
|
||||
return;
|
||||
}
|
||||
await transport.handlePostMessage(req, res);
|
||||
});
|
||||
app.listen(port, () => {
|
||||
console.log(`Server running on http://localhost:${port}/sse`);
|
||||
});
|
||||
}
|
||||
else {
|
||||
const server = new index_js_2.Server({
|
||||
name: "mcp-typescript test server",
|
||||
version: "0.1.0",
|
||||
}, {
|
||||
capabilities: {
|
||||
prompts: {},
|
||||
resources: {},
|
||||
tools: {},
|
||||
logging: {},
|
||||
},
|
||||
});
|
||||
const transport = new stdio_js_2.StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
console.log("Server running on stdio");
|
||||
}
|
||||
}
|
||||
const args = process.argv.slice(2);
|
||||
const command = args[0];
|
||||
switch (command) {
|
||||
case "client":
|
||||
if (args.length < 2) {
|
||||
console.error("Usage: client <server_url_or_command> [args...]");
|
||||
process.exit(1);
|
||||
}
|
||||
runClient(args[1], args.slice(2)).catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
break;
|
||||
case "server": {
|
||||
const port = args[1] ? parseInt(args[1]) : null;
|
||||
runServer(port).catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.error("Unrecognized command:", command);
|
||||
}
|
||||
//# sourceMappingURL=cli.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/cli.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/cli.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|
||||
151
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.d.ts
generated
vendored
Normal file
151
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.d.ts
generated
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
import type { OAuthClientMetadata, OAuthClientInformation, OAuthTokens, OAuthMetadata, OAuthClientInformationFull, OAuthProtectedResourceMetadata } from "../shared/auth.js";
|
||||
/**
|
||||
* Implements an end-to-end OAuth client to be used with one MCP server.
|
||||
*
|
||||
* This client relies upon a concept of an authorized "session," the exact
|
||||
* meaning of which is application-defined. Tokens, authorization codes, and
|
||||
* code verifiers should not cross different sessions.
|
||||
*/
|
||||
export interface OAuthClientProvider {
|
||||
/**
|
||||
* The URL to redirect the user agent to after authorization.
|
||||
*/
|
||||
get redirectUrl(): string | URL;
|
||||
/**
|
||||
* Metadata about this OAuth client.
|
||||
*/
|
||||
get clientMetadata(): OAuthClientMetadata;
|
||||
/**
|
||||
* Returns a OAuth2 state parameter.
|
||||
*/
|
||||
state?(): string | Promise<string>;
|
||||
/**
|
||||
* Loads information about this OAuth client, as registered already with the
|
||||
* server, or returns `undefined` if the client is not registered with the
|
||||
* server.
|
||||
*/
|
||||
clientInformation(): OAuthClientInformation | undefined | Promise<OAuthClientInformation | undefined>;
|
||||
/**
|
||||
* If implemented, this permits the OAuth client to dynamically register with
|
||||
* the server. Client information saved this way should later be read via
|
||||
* `clientInformation()`.
|
||||
*
|
||||
* This method is not required to be implemented if client information is
|
||||
* statically known (e.g., pre-registered).
|
||||
*/
|
||||
saveClientInformation?(clientInformation: OAuthClientInformationFull): void | Promise<void>;
|
||||
/**
|
||||
* Loads any existing OAuth tokens for the current session, or returns
|
||||
* `undefined` if there are no saved tokens.
|
||||
*/
|
||||
tokens(): OAuthTokens | undefined | Promise<OAuthTokens | undefined>;
|
||||
/**
|
||||
* Stores new OAuth tokens for the current session, after a successful
|
||||
* authorization.
|
||||
*/
|
||||
saveTokens(tokens: OAuthTokens): void | Promise<void>;
|
||||
/**
|
||||
* Invoked to redirect the user agent to the given URL to begin the authorization flow.
|
||||
*/
|
||||
redirectToAuthorization(authorizationUrl: URL): void | Promise<void>;
|
||||
/**
|
||||
* Saves a PKCE code verifier for the current session, before redirecting to
|
||||
* the authorization flow.
|
||||
*/
|
||||
saveCodeVerifier(codeVerifier: string): void | Promise<void>;
|
||||
/**
|
||||
* Loads the PKCE code verifier for the current session, necessary to validate
|
||||
* the authorization result.
|
||||
*/
|
||||
codeVerifier(): string | Promise<string>;
|
||||
/**
|
||||
* If defined, overrides the selection and validation of the
|
||||
* RFC 8707 Resource Indicator. If left undefined, default
|
||||
* validation behavior will be used.
|
||||
*
|
||||
* Implementations must verify the returned resource matches the MCP server.
|
||||
*/
|
||||
validateResourceURL?(serverUrl: string | URL, resource?: string): Promise<URL | undefined>;
|
||||
}
|
||||
export type AuthResult = "AUTHORIZED" | "REDIRECT";
|
||||
export declare class UnauthorizedError extends Error {
|
||||
constructor(message?: string);
|
||||
}
|
||||
/**
|
||||
* Orchestrates the full auth flow with a server.
|
||||
*
|
||||
* This can be used as a single entry point for all authorization functionality,
|
||||
* instead of linking together the other lower-level functions in this module.
|
||||
*/
|
||||
export declare function auth(provider: OAuthClientProvider, { serverUrl, authorizationCode, scope, resourceMetadataUrl }: {
|
||||
serverUrl: string | URL;
|
||||
authorizationCode?: string;
|
||||
scope?: string;
|
||||
resourceMetadataUrl?: URL;
|
||||
}): Promise<AuthResult>;
|
||||
export declare function selectResourceURL(serverUrl: string | URL, provider: OAuthClientProvider, resourceMetadata?: OAuthProtectedResourceMetadata): Promise<URL | undefined>;
|
||||
/**
|
||||
* Extract resource_metadata from response header.
|
||||
*/
|
||||
export declare function extractResourceMetadataUrl(res: Response): URL | undefined;
|
||||
/**
|
||||
* Looks up RFC 9728 OAuth 2.0 Protected Resource Metadata.
|
||||
*
|
||||
* If the server returns a 404 for the well-known endpoint, this function will
|
||||
* return `undefined`. Any other errors will be thrown as exceptions.
|
||||
*/
|
||||
export declare function discoverOAuthProtectedResourceMetadata(serverUrl: string | URL, opts?: {
|
||||
protocolVersion?: string;
|
||||
resourceMetadataUrl?: string | URL;
|
||||
}): Promise<OAuthProtectedResourceMetadata>;
|
||||
/**
|
||||
* Looks up RFC 8414 OAuth 2.0 Authorization Server Metadata.
|
||||
*
|
||||
* If the server returns a 404 for the well-known endpoint, this function will
|
||||
* return `undefined`. Any other errors will be thrown as exceptions.
|
||||
*/
|
||||
export declare function discoverOAuthMetadata(authorizationServerUrl: string | URL, opts?: {
|
||||
protocolVersion?: string;
|
||||
}): Promise<OAuthMetadata | undefined>;
|
||||
/**
|
||||
* Begins the authorization flow with the given server, by generating a PKCE challenge and constructing the authorization URL.
|
||||
*/
|
||||
export declare function startAuthorization(authorizationServerUrl: string | URL, { metadata, clientInformation, redirectUrl, scope, state, resource, }: {
|
||||
metadata?: OAuthMetadata;
|
||||
clientInformation: OAuthClientInformation;
|
||||
redirectUrl: string | URL;
|
||||
scope?: string;
|
||||
state?: string;
|
||||
resource?: URL;
|
||||
}): Promise<{
|
||||
authorizationUrl: URL;
|
||||
codeVerifier: string;
|
||||
}>;
|
||||
/**
|
||||
* Exchanges an authorization code for an access token with the given server.
|
||||
*/
|
||||
export declare function exchangeAuthorization(authorizationServerUrl: string | URL, { metadata, clientInformation, authorizationCode, codeVerifier, redirectUri, resource, }: {
|
||||
metadata?: OAuthMetadata;
|
||||
clientInformation: OAuthClientInformation;
|
||||
authorizationCode: string;
|
||||
codeVerifier: string;
|
||||
redirectUri: string | URL;
|
||||
resource?: URL;
|
||||
}): Promise<OAuthTokens>;
|
||||
/**
|
||||
* Exchange a refresh token for an updated access token.
|
||||
*/
|
||||
export declare function refreshAuthorization(authorizationServerUrl: string | URL, { metadata, clientInformation, refreshToken, resource, }: {
|
||||
metadata?: OAuthMetadata;
|
||||
clientInformation: OAuthClientInformation;
|
||||
refreshToken: string;
|
||||
resource?: URL;
|
||||
}): Promise<OAuthTokens>;
|
||||
/**
|
||||
* Performs OAuth 2.0 Dynamic Client Registration according to RFC 7591.
|
||||
*/
|
||||
export declare function registerClient(authorizationServerUrl: string | URL, { metadata, clientMetadata, }: {
|
||||
metadata?: OAuthMetadata;
|
||||
clientMetadata: OAuthClientMetadata;
|
||||
}): Promise<OAuthClientInformationFull>;
|
||||
//# sourceMappingURL=auth.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/client/auth.ts"],"names":[],"mappings":"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"}
|
||||
411
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js
generated
vendored
Normal file
411
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js
generated
vendored
Normal file
@@ -0,0 +1,411 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UnauthorizedError = void 0;
|
||||
exports.auth = auth;
|
||||
exports.selectResourceURL = selectResourceURL;
|
||||
exports.extractResourceMetadataUrl = extractResourceMetadataUrl;
|
||||
exports.discoverOAuthProtectedResourceMetadata = discoverOAuthProtectedResourceMetadata;
|
||||
exports.discoverOAuthMetadata = discoverOAuthMetadata;
|
||||
exports.startAuthorization = startAuthorization;
|
||||
exports.exchangeAuthorization = exchangeAuthorization;
|
||||
exports.refreshAuthorization = refreshAuthorization;
|
||||
exports.registerClient = registerClient;
|
||||
const pkce_challenge_1 = __importDefault(require("pkce-challenge"));
|
||||
const types_js_1 = require("../types.js");
|
||||
const auth_js_1 = require("../shared/auth.js");
|
||||
const auth_utils_js_1 = require("../shared/auth-utils.js");
|
||||
class UnauthorizedError extends Error {
|
||||
constructor(message) {
|
||||
super(message !== null && message !== void 0 ? message : "Unauthorized");
|
||||
}
|
||||
}
|
||||
exports.UnauthorizedError = UnauthorizedError;
|
||||
/**
|
||||
* Orchestrates the full auth flow with a server.
|
||||
*
|
||||
* This can be used as a single entry point for all authorization functionality,
|
||||
* instead of linking together the other lower-level functions in this module.
|
||||
*/
|
||||
async function auth(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl }) {
|
||||
let resourceMetadata;
|
||||
let authorizationServerUrl = serverUrl;
|
||||
try {
|
||||
resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl });
|
||||
if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) {
|
||||
authorizationServerUrl = resourceMetadata.authorization_servers[0];
|
||||
}
|
||||
}
|
||||
catch (_a) {
|
||||
// Ignore errors and fall back to /.well-known/oauth-authorization-server
|
||||
}
|
||||
const resource = await selectResourceURL(serverUrl, provider, resourceMetadata);
|
||||
const metadata = await discoverOAuthMetadata(authorizationServerUrl);
|
||||
// Handle client registration if needed
|
||||
let clientInformation = await Promise.resolve(provider.clientInformation());
|
||||
if (!clientInformation) {
|
||||
if (authorizationCode !== undefined) {
|
||||
throw new Error("Existing OAuth client information is required when exchanging an authorization code");
|
||||
}
|
||||
if (!provider.saveClientInformation) {
|
||||
throw new Error("OAuth client information must be saveable for dynamic registration");
|
||||
}
|
||||
const fullInformation = await registerClient(authorizationServerUrl, {
|
||||
metadata,
|
||||
clientMetadata: provider.clientMetadata,
|
||||
});
|
||||
await provider.saveClientInformation(fullInformation);
|
||||
clientInformation = fullInformation;
|
||||
}
|
||||
// Exchange authorization code for tokens
|
||||
if (authorizationCode !== undefined) {
|
||||
const codeVerifier = await provider.codeVerifier();
|
||||
const tokens = await exchangeAuthorization(authorizationServerUrl, {
|
||||
metadata,
|
||||
clientInformation,
|
||||
authorizationCode,
|
||||
codeVerifier,
|
||||
redirectUri: provider.redirectUrl,
|
||||
resource,
|
||||
});
|
||||
await provider.saveTokens(tokens);
|
||||
return "AUTHORIZED";
|
||||
}
|
||||
const tokens = await provider.tokens();
|
||||
// Handle token refresh or new authorization
|
||||
if (tokens === null || tokens === void 0 ? void 0 : tokens.refresh_token) {
|
||||
try {
|
||||
// Attempt to refresh the token
|
||||
const newTokens = await refreshAuthorization(authorizationServerUrl, {
|
||||
metadata,
|
||||
clientInformation,
|
||||
refreshToken: tokens.refresh_token,
|
||||
resource,
|
||||
});
|
||||
await provider.saveTokens(newTokens);
|
||||
return "AUTHORIZED";
|
||||
}
|
||||
catch (_b) {
|
||||
// Could not refresh OAuth tokens
|
||||
}
|
||||
}
|
||||
const state = provider.state ? await provider.state() : undefined;
|
||||
// Start new authorization flow
|
||||
const { authorizationUrl, codeVerifier } = await startAuthorization(authorizationServerUrl, {
|
||||
metadata,
|
||||
clientInformation,
|
||||
state,
|
||||
redirectUrl: provider.redirectUrl,
|
||||
scope: scope || provider.clientMetadata.scope,
|
||||
resource,
|
||||
});
|
||||
await provider.saveCodeVerifier(codeVerifier);
|
||||
await provider.redirectToAuthorization(authorizationUrl);
|
||||
return "REDIRECT";
|
||||
}
|
||||
async function selectResourceURL(serverUrl, provider, resourceMetadata) {
|
||||
const defaultResource = (0, auth_utils_js_1.resourceUrlFromServerUrl)(serverUrl);
|
||||
// If provider has custom validation, delegate to it
|
||||
if (provider.validateResourceURL) {
|
||||
return await provider.validateResourceURL(defaultResource, resourceMetadata === null || resourceMetadata === void 0 ? void 0 : resourceMetadata.resource);
|
||||
}
|
||||
// Only include resource parameter when Protected Resource Metadata is present
|
||||
if (!resourceMetadata) {
|
||||
return undefined;
|
||||
}
|
||||
// Validate that the metadata's resource is compatible with our request
|
||||
if (!(0, auth_utils_js_1.checkResourceAllowed)({ requestedResource: defaultResource, configuredResource: resourceMetadata.resource })) {
|
||||
throw new Error(`Protected resource ${resourceMetadata.resource} does not match expected ${defaultResource} (or origin)`);
|
||||
}
|
||||
// Prefer the resource from metadata since it's what the server is telling us to request
|
||||
return new URL(resourceMetadata.resource);
|
||||
}
|
||||
/**
|
||||
* Extract resource_metadata from response header.
|
||||
*/
|
||||
function extractResourceMetadataUrl(res) {
|
||||
const authenticateHeader = res.headers.get("WWW-Authenticate");
|
||||
if (!authenticateHeader) {
|
||||
return undefined;
|
||||
}
|
||||
const [type, scheme] = authenticateHeader.split(' ');
|
||||
if (type.toLowerCase() !== 'bearer' || !scheme) {
|
||||
return undefined;
|
||||
}
|
||||
const regex = /resource_metadata="([^"]*)"/;
|
||||
const match = regex.exec(authenticateHeader);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
try {
|
||||
return new URL(match[1]);
|
||||
}
|
||||
catch (_a) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Looks up RFC 9728 OAuth 2.0 Protected Resource Metadata.
|
||||
*
|
||||
* If the server returns a 404 for the well-known endpoint, this function will
|
||||
* return `undefined`. Any other errors will be thrown as exceptions.
|
||||
*/
|
||||
async function discoverOAuthProtectedResourceMetadata(serverUrl, opts) {
|
||||
var _a;
|
||||
let url;
|
||||
if (opts === null || opts === void 0 ? void 0 : opts.resourceMetadataUrl) {
|
||||
url = new URL(opts === null || opts === void 0 ? void 0 : opts.resourceMetadataUrl);
|
||||
}
|
||||
else {
|
||||
url = new URL("/.well-known/oauth-protected-resource", serverUrl);
|
||||
}
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(url, {
|
||||
headers: {
|
||||
"MCP-Protocol-Version": (_a = opts === null || opts === void 0 ? void 0 : opts.protocolVersion) !== null && _a !== void 0 ? _a : types_js_1.LATEST_PROTOCOL_VERSION
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
// CORS errors come back as TypeError
|
||||
if (error instanceof TypeError) {
|
||||
response = await fetch(url);
|
||||
}
|
||||
else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
if (response.status === 404) {
|
||||
throw new Error(`Resource server does not implement OAuth 2.0 Protected Resource Metadata.`);
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status} trying to load well-known OAuth protected resource metadata.`);
|
||||
}
|
||||
return auth_js_1.OAuthProtectedResourceMetadataSchema.parse(await response.json());
|
||||
}
|
||||
/**
|
||||
* Helper function to handle fetch with CORS retry logic
|
||||
*/
|
||||
async function fetchWithCorsRetry(url, headers) {
|
||||
try {
|
||||
return await fetch(url, { headers });
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
if (headers) {
|
||||
// CORS errors come back as TypeError, retry without headers
|
||||
return fetchWithCorsRetry(url);
|
||||
}
|
||||
else {
|
||||
// We're getting CORS errors on retry too, return undefined
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Constructs the well-known path for OAuth metadata discovery
|
||||
*/
|
||||
function buildWellKnownPath(pathname) {
|
||||
let wellKnownPath = `/.well-known/oauth-authorization-server${pathname}`;
|
||||
if (pathname.endsWith('/')) {
|
||||
// Strip trailing slash from pathname to avoid double slashes
|
||||
wellKnownPath = wellKnownPath.slice(0, -1);
|
||||
}
|
||||
return wellKnownPath;
|
||||
}
|
||||
/**
|
||||
* Tries to discover OAuth metadata at a specific URL
|
||||
*/
|
||||
async function tryMetadataDiscovery(url, protocolVersion) {
|
||||
const headers = {
|
||||
"MCP-Protocol-Version": protocolVersion
|
||||
};
|
||||
return await fetchWithCorsRetry(url, headers);
|
||||
}
|
||||
/**
|
||||
* Determines if fallback to root discovery should be attempted
|
||||
*/
|
||||
function shouldAttemptFallback(response, pathname) {
|
||||
return !response || response.status === 404 && pathname !== '/';
|
||||
}
|
||||
/**
|
||||
* Looks up RFC 8414 OAuth 2.0 Authorization Server Metadata.
|
||||
*
|
||||
* If the server returns a 404 for the well-known endpoint, this function will
|
||||
* return `undefined`. Any other errors will be thrown as exceptions.
|
||||
*/
|
||||
async function discoverOAuthMetadata(authorizationServerUrl, opts) {
|
||||
var _a;
|
||||
const issuer = new URL(authorizationServerUrl);
|
||||
const protocolVersion = (_a = opts === null || opts === void 0 ? void 0 : opts.protocolVersion) !== null && _a !== void 0 ? _a : types_js_1.LATEST_PROTOCOL_VERSION;
|
||||
// Try path-aware discovery first (RFC 8414 compliant)
|
||||
const wellKnownPath = buildWellKnownPath(issuer.pathname);
|
||||
const pathAwareUrl = new URL(wellKnownPath, issuer);
|
||||
let response = await tryMetadataDiscovery(pathAwareUrl, protocolVersion);
|
||||
// If path-aware discovery fails with 404, try fallback to root discovery
|
||||
if (shouldAttemptFallback(response, issuer.pathname)) {
|
||||
const rootUrl = new URL("/.well-known/oauth-authorization-server", issuer);
|
||||
response = await tryMetadataDiscovery(rootUrl, protocolVersion);
|
||||
}
|
||||
if (!response || response.status === 404) {
|
||||
return undefined;
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status} trying to load well-known OAuth metadata`);
|
||||
}
|
||||
return auth_js_1.OAuthMetadataSchema.parse(await response.json());
|
||||
}
|
||||
/**
|
||||
* Begins the authorization flow with the given server, by generating a PKCE challenge and constructing the authorization URL.
|
||||
*/
|
||||
async function startAuthorization(authorizationServerUrl, { metadata, clientInformation, redirectUrl, scope, state, resource, }) {
|
||||
const responseType = "code";
|
||||
const codeChallengeMethod = "S256";
|
||||
let authorizationUrl;
|
||||
if (metadata) {
|
||||
authorizationUrl = new URL(metadata.authorization_endpoint);
|
||||
if (!metadata.response_types_supported.includes(responseType)) {
|
||||
throw new Error(`Incompatible auth server: does not support response type ${responseType}`);
|
||||
}
|
||||
if (!metadata.code_challenge_methods_supported ||
|
||||
!metadata.code_challenge_methods_supported.includes(codeChallengeMethod)) {
|
||||
throw new Error(`Incompatible auth server: does not support code challenge method ${codeChallengeMethod}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
authorizationUrl = new URL("/authorize", authorizationServerUrl);
|
||||
}
|
||||
// Generate PKCE challenge
|
||||
const challenge = await (0, pkce_challenge_1.default)();
|
||||
const codeVerifier = challenge.code_verifier;
|
||||
const codeChallenge = challenge.code_challenge;
|
||||
authorizationUrl.searchParams.set("response_type", responseType);
|
||||
authorizationUrl.searchParams.set("client_id", clientInformation.client_id);
|
||||
authorizationUrl.searchParams.set("code_challenge", codeChallenge);
|
||||
authorizationUrl.searchParams.set("code_challenge_method", codeChallengeMethod);
|
||||
authorizationUrl.searchParams.set("redirect_uri", String(redirectUrl));
|
||||
if (state) {
|
||||
authorizationUrl.searchParams.set("state", state);
|
||||
}
|
||||
if (scope) {
|
||||
authorizationUrl.searchParams.set("scope", scope);
|
||||
}
|
||||
if (resource) {
|
||||
authorizationUrl.searchParams.set("resource", resource.href);
|
||||
}
|
||||
return { authorizationUrl, codeVerifier };
|
||||
}
|
||||
/**
|
||||
* Exchanges an authorization code for an access token with the given server.
|
||||
*/
|
||||
async function exchangeAuthorization(authorizationServerUrl, { metadata, clientInformation, authorizationCode, codeVerifier, redirectUri, resource, }) {
|
||||
const grantType = "authorization_code";
|
||||
let tokenUrl;
|
||||
if (metadata) {
|
||||
tokenUrl = new URL(metadata.token_endpoint);
|
||||
if (metadata.grant_types_supported &&
|
||||
!metadata.grant_types_supported.includes(grantType)) {
|
||||
throw new Error(`Incompatible auth server: does not support grant type ${grantType}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tokenUrl = new URL("/token", authorizationServerUrl);
|
||||
}
|
||||
// Exchange code for tokens
|
||||
const params = new URLSearchParams({
|
||||
grant_type: grantType,
|
||||
client_id: clientInformation.client_id,
|
||||
code: authorizationCode,
|
||||
code_verifier: codeVerifier,
|
||||
redirect_uri: String(redirectUri),
|
||||
});
|
||||
if (clientInformation.client_secret) {
|
||||
params.set("client_secret", clientInformation.client_secret);
|
||||
}
|
||||
if (resource) {
|
||||
params.set("resource", resource.href);
|
||||
}
|
||||
const response = await fetch(tokenUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
body: params,
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Token exchange failed: HTTP ${response.status}`);
|
||||
}
|
||||
return auth_js_1.OAuthTokensSchema.parse(await response.json());
|
||||
}
|
||||
/**
|
||||
* Exchange a refresh token for an updated access token.
|
||||
*/
|
||||
async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, }) {
|
||||
const grantType = "refresh_token";
|
||||
let tokenUrl;
|
||||
if (metadata) {
|
||||
tokenUrl = new URL(metadata.token_endpoint);
|
||||
if (metadata.grant_types_supported &&
|
||||
!metadata.grant_types_supported.includes(grantType)) {
|
||||
throw new Error(`Incompatible auth server: does not support grant type ${grantType}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tokenUrl = new URL("/token", authorizationServerUrl);
|
||||
}
|
||||
// Exchange refresh token
|
||||
const params = new URLSearchParams({
|
||||
grant_type: grantType,
|
||||
client_id: clientInformation.client_id,
|
||||
refresh_token: refreshToken,
|
||||
});
|
||||
if (clientInformation.client_secret) {
|
||||
params.set("client_secret", clientInformation.client_secret);
|
||||
}
|
||||
if (resource) {
|
||||
params.set("resource", resource.href);
|
||||
}
|
||||
const response = await fetch(tokenUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
body: params,
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Token refresh failed: HTTP ${response.status}`);
|
||||
}
|
||||
return auth_js_1.OAuthTokensSchema.parse({ refresh_token: refreshToken, ...(await response.json()) });
|
||||
}
|
||||
/**
|
||||
* Performs OAuth 2.0 Dynamic Client Registration according to RFC 7591.
|
||||
*/
|
||||
async function registerClient(authorizationServerUrl, { metadata, clientMetadata, }) {
|
||||
let registrationUrl;
|
||||
if (metadata) {
|
||||
if (!metadata.registration_endpoint) {
|
||||
throw new Error("Incompatible auth server: does not support dynamic client registration");
|
||||
}
|
||||
registrationUrl = new URL(metadata.registration_endpoint);
|
||||
}
|
||||
else {
|
||||
registrationUrl = new URL("/register", authorizationServerUrl);
|
||||
}
|
||||
const response = await fetch(registrationUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(clientMetadata),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Dynamic client registration failed: HTTP ${response.status}`);
|
||||
}
|
||||
return auth_js_1.OAuthClientInformationFullSchema.parse(await response.json());
|
||||
}
|
||||
//# sourceMappingURL=auth.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1224
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.d.ts
generated
vendored
Normal file
1224
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"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"}
|
||||
295
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.js
generated
vendored
Normal file
295
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.js
generated
vendored
Normal file
@@ -0,0 +1,295 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Client = void 0;
|
||||
const protocol_js_1 = require("../shared/protocol.js");
|
||||
const types_js_1 = require("../types.js");
|
||||
const ajv_1 = __importDefault(require("ajv"));
|
||||
/**
|
||||
* An MCP client on top of a pluggable transport.
|
||||
*
|
||||
* The client will automatically begin the initialization flow with the server when connect() is called.
|
||||
*
|
||||
* To use with custom types, extend the base Request/Notification/Result types and pass them as type parameters:
|
||||
*
|
||||
* ```typescript
|
||||
* // Custom schemas
|
||||
* const CustomRequestSchema = RequestSchema.extend({...})
|
||||
* const CustomNotificationSchema = NotificationSchema.extend({...})
|
||||
* const CustomResultSchema = ResultSchema.extend({...})
|
||||
*
|
||||
* // Type aliases
|
||||
* type CustomRequest = z.infer<typeof CustomRequestSchema>
|
||||
* type CustomNotification = z.infer<typeof CustomNotificationSchema>
|
||||
* type CustomResult = z.infer<typeof CustomResultSchema>
|
||||
*
|
||||
* // Create typed client
|
||||
* const client = new Client<CustomRequest, CustomNotification, CustomResult>({
|
||||
* name: "CustomClient",
|
||||
* version: "1.0.0"
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
class Client extends protocol_js_1.Protocol {
|
||||
/**
|
||||
* Initializes this client with the given name and version information.
|
||||
*/
|
||||
constructor(_clientInfo, options) {
|
||||
var _a;
|
||||
super(options);
|
||||
this._clientInfo = _clientInfo;
|
||||
this._cachedToolOutputValidators = new Map();
|
||||
this._capabilities = (_a = options === null || options === void 0 ? void 0 : options.capabilities) !== null && _a !== void 0 ? _a : {};
|
||||
this._ajv = new ajv_1.default();
|
||||
}
|
||||
/**
|
||||
* Registers new capabilities. This can only be called before connecting to a transport.
|
||||
*
|
||||
* The new capabilities will be merged with any existing capabilities previously given (e.g., at initialization).
|
||||
*/
|
||||
registerCapabilities(capabilities) {
|
||||
if (this.transport) {
|
||||
throw new Error("Cannot register capabilities after connecting to transport");
|
||||
}
|
||||
this._capabilities = (0, protocol_js_1.mergeCapabilities)(this._capabilities, capabilities);
|
||||
}
|
||||
assertCapability(capability, method) {
|
||||
var _a;
|
||||
if (!((_a = this._serverCapabilities) === null || _a === void 0 ? void 0 : _a[capability])) {
|
||||
throw new Error(`Server does not support ${capability} (required for ${method})`);
|
||||
}
|
||||
}
|
||||
async connect(transport, options) {
|
||||
await super.connect(transport);
|
||||
// When transport sessionId is already set this means we are trying to reconnect.
|
||||
// In this case we don't need to initialize again.
|
||||
if (transport.sessionId !== undefined) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const result = await this.request({
|
||||
method: "initialize",
|
||||
params: {
|
||||
protocolVersion: types_js_1.LATEST_PROTOCOL_VERSION,
|
||||
capabilities: this._capabilities,
|
||||
clientInfo: this._clientInfo,
|
||||
},
|
||||
}, types_js_1.InitializeResultSchema, options);
|
||||
if (result === undefined) {
|
||||
throw new Error(`Server sent invalid initialize result: ${result}`);
|
||||
}
|
||||
if (!types_js_1.SUPPORTED_PROTOCOL_VERSIONS.includes(result.protocolVersion)) {
|
||||
throw new Error(`Server's protocol version is not supported: ${result.protocolVersion}`);
|
||||
}
|
||||
this._serverCapabilities = result.capabilities;
|
||||
this._serverVersion = result.serverInfo;
|
||||
// HTTP transports must set the protocol version in each header after initialization.
|
||||
if (transport.setProtocolVersion) {
|
||||
transport.setProtocolVersion(result.protocolVersion);
|
||||
}
|
||||
this._instructions = result.instructions;
|
||||
await this.notification({
|
||||
method: "notifications/initialized",
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
// Disconnect if initialization fails.
|
||||
void this.close();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* After initialization has completed, this will be populated with the server's reported capabilities.
|
||||
*/
|
||||
getServerCapabilities() {
|
||||
return this._serverCapabilities;
|
||||
}
|
||||
/**
|
||||
* After initialization has completed, this will be populated with information about the server's name and version.
|
||||
*/
|
||||
getServerVersion() {
|
||||
return this._serverVersion;
|
||||
}
|
||||
/**
|
||||
* After initialization has completed, this may be populated with information about the server's instructions.
|
||||
*/
|
||||
getInstructions() {
|
||||
return this._instructions;
|
||||
}
|
||||
assertCapabilityForMethod(method) {
|
||||
var _a, _b, _c, _d, _e;
|
||||
switch (method) {
|
||||
case "logging/setLevel":
|
||||
if (!((_a = this._serverCapabilities) === null || _a === void 0 ? void 0 : _a.logging)) {
|
||||
throw new Error(`Server does not support logging (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case "prompts/get":
|
||||
case "prompts/list":
|
||||
if (!((_b = this._serverCapabilities) === null || _b === void 0 ? void 0 : _b.prompts)) {
|
||||
throw new Error(`Server does not support prompts (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case "resources/list":
|
||||
case "resources/templates/list":
|
||||
case "resources/read":
|
||||
case "resources/subscribe":
|
||||
case "resources/unsubscribe":
|
||||
if (!((_c = this._serverCapabilities) === null || _c === void 0 ? void 0 : _c.resources)) {
|
||||
throw new Error(`Server does not support resources (required for ${method})`);
|
||||
}
|
||||
if (method === "resources/subscribe" &&
|
||||
!this._serverCapabilities.resources.subscribe) {
|
||||
throw new Error(`Server does not support resource subscriptions (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case "tools/call":
|
||||
case "tools/list":
|
||||
if (!((_d = this._serverCapabilities) === null || _d === void 0 ? void 0 : _d.tools)) {
|
||||
throw new Error(`Server does not support tools (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case "completion/complete":
|
||||
if (!((_e = this._serverCapabilities) === null || _e === void 0 ? void 0 : _e.completions)) {
|
||||
throw new Error(`Server does not support completions (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case "initialize":
|
||||
// No specific capability required for initialize
|
||||
break;
|
||||
case "ping":
|
||||
// No specific capability required for ping
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertNotificationCapability(method) {
|
||||
var _a;
|
||||
switch (method) {
|
||||
case "notifications/roots/list_changed":
|
||||
if (!((_a = this._capabilities.roots) === null || _a === void 0 ? void 0 : _a.listChanged)) {
|
||||
throw new Error(`Client does not support roots list changed notifications (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case "notifications/initialized":
|
||||
// No specific capability required for initialized
|
||||
break;
|
||||
case "notifications/cancelled":
|
||||
// Cancellation notifications are always allowed
|
||||
break;
|
||||
case "notifications/progress":
|
||||
// Progress notifications are always allowed
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertRequestHandlerCapability(method) {
|
||||
switch (method) {
|
||||
case "sampling/createMessage":
|
||||
if (!this._capabilities.sampling) {
|
||||
throw new Error(`Client does not support sampling capability (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case "elicitation/create":
|
||||
if (!this._capabilities.elicitation) {
|
||||
throw new Error(`Client does not support elicitation capability (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case "roots/list":
|
||||
if (!this._capabilities.roots) {
|
||||
throw new Error(`Client does not support roots capability (required for ${method})`);
|
||||
}
|
||||
break;
|
||||
case "ping":
|
||||
// No specific capability required for ping
|
||||
break;
|
||||
}
|
||||
}
|
||||
async ping(options) {
|
||||
return this.request({ method: "ping" }, types_js_1.EmptyResultSchema, options);
|
||||
}
|
||||
async complete(params, options) {
|
||||
return this.request({ method: "completion/complete", params }, types_js_1.CompleteResultSchema, options);
|
||||
}
|
||||
async setLoggingLevel(level, options) {
|
||||
return this.request({ method: "logging/setLevel", params: { level } }, types_js_1.EmptyResultSchema, options);
|
||||
}
|
||||
async getPrompt(params, options) {
|
||||
return this.request({ method: "prompts/get", params }, types_js_1.GetPromptResultSchema, options);
|
||||
}
|
||||
async listPrompts(params, options) {
|
||||
return this.request({ method: "prompts/list", params }, types_js_1.ListPromptsResultSchema, options);
|
||||
}
|
||||
async listResources(params, options) {
|
||||
return this.request({ method: "resources/list", params }, types_js_1.ListResourcesResultSchema, options);
|
||||
}
|
||||
async listResourceTemplates(params, options) {
|
||||
return this.request({ method: "resources/templates/list", params }, types_js_1.ListResourceTemplatesResultSchema, options);
|
||||
}
|
||||
async readResource(params, options) {
|
||||
return this.request({ method: "resources/read", params }, types_js_1.ReadResourceResultSchema, options);
|
||||
}
|
||||
async subscribeResource(params, options) {
|
||||
return this.request({ method: "resources/subscribe", params }, types_js_1.EmptyResultSchema, options);
|
||||
}
|
||||
async unsubscribeResource(params, options) {
|
||||
return this.request({ method: "resources/unsubscribe", params }, types_js_1.EmptyResultSchema, options);
|
||||
}
|
||||
async callTool(params, resultSchema = types_js_1.CallToolResultSchema, options) {
|
||||
const result = await this.request({ method: "tools/call", params }, resultSchema, options);
|
||||
// Check if the tool has an outputSchema
|
||||
const validator = this.getToolOutputValidator(params.name);
|
||||
if (validator) {
|
||||
// If tool has outputSchema, it MUST return structuredContent (unless it's an error)
|
||||
if (!result.structuredContent && !result.isError) {
|
||||
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `Tool ${params.name} has an output schema but did not return structured content`);
|
||||
}
|
||||
// Only validate structured content if present (not when there's an error)
|
||||
if (result.structuredContent) {
|
||||
try {
|
||||
// Validate the structured content (which is already an object) against the schema
|
||||
const isValid = validator(result.structuredContent);
|
||||
if (!isValid) {
|
||||
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${this._ajv.errorsText(validator.errors)}`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof types_js_1.McpError) {
|
||||
throw error;
|
||||
}
|
||||
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, `Failed to validate structured content: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
cacheToolOutputSchemas(tools) {
|
||||
this._cachedToolOutputValidators.clear();
|
||||
for (const tool of tools) {
|
||||
// If the tool has an outputSchema, create and cache the Ajv validator
|
||||
if (tool.outputSchema) {
|
||||
try {
|
||||
const validator = this._ajv.compile(tool.outputSchema);
|
||||
this._cachedToolOutputValidators.set(tool.name, validator);
|
||||
}
|
||||
catch (_a) {
|
||||
// Ignore schema compilation errors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
getToolOutputValidator(toolName) {
|
||||
return this._cachedToolOutputValidators.get(toolName);
|
||||
}
|
||||
async listTools(params, options) {
|
||||
const result = await this.request({ method: "tools/list", params }, types_js_1.ListToolsResultSchema, options);
|
||||
// Cache the tools and their output schemas for future validation
|
||||
this.cacheToolOutputSchemas(result.tools);
|
||||
return result;
|
||||
}
|
||||
async sendRootsListChanged() {
|
||||
return this.notification({ method: "notifications/roots/list_changed" });
|
||||
}
|
||||
}
|
||||
exports.Client = Client;
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
78
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/sse.d.ts
generated
vendored
Normal file
78
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/sse.d.ts
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
import { type ErrorEvent, type EventSourceInit } from "eventsource";
|
||||
import { Transport, FetchLike } from "../shared/transport.js";
|
||||
import { JSONRPCMessage } from "../types.js";
|
||||
import { OAuthClientProvider } from "./auth.js";
|
||||
export declare class SseError extends Error {
|
||||
readonly code: number | undefined;
|
||||
readonly event: ErrorEvent;
|
||||
constructor(code: number | undefined, message: string | undefined, event: ErrorEvent);
|
||||
}
|
||||
/**
|
||||
* Configuration options for the `SSEClientTransport`.
|
||||
*/
|
||||
export type SSEClientTransportOptions = {
|
||||
/**
|
||||
* An OAuth client provider to use for authentication.
|
||||
*
|
||||
* When an `authProvider` is specified and the SSE connection is started:
|
||||
* 1. The connection is attempted with any existing access token from the `authProvider`.
|
||||
* 2. If the access token has expired, the `authProvider` is used to refresh the token.
|
||||
* 3. If token refresh fails or no access token exists, and auth is required, `OAuthClientProvider.redirectToAuthorization` is called, and an `UnauthorizedError` will be thrown from `connect`/`start`.
|
||||
*
|
||||
* After the user has finished authorizing via their user agent, and is redirected back to the MCP client application, call `SSEClientTransport.finishAuth` with the authorization code before retrying the connection.
|
||||
*
|
||||
* If an `authProvider` is not provided, and auth is required, an `UnauthorizedError` will be thrown.
|
||||
*
|
||||
* `UnauthorizedError` might also be thrown when sending any message over the SSE transport, indicating that the session has expired, and needs to be re-authed and reconnected.
|
||||
*/
|
||||
authProvider?: OAuthClientProvider;
|
||||
/**
|
||||
* Customizes the initial SSE request to the server (the request that begins the stream).
|
||||
*
|
||||
* NOTE: Setting this property will prevent an `Authorization` header from
|
||||
* being automatically attached to the SSE request, if an `authProvider` is
|
||||
* also given. This can be worked around by setting the `Authorization` header
|
||||
* manually.
|
||||
*/
|
||||
eventSourceInit?: EventSourceInit;
|
||||
/**
|
||||
* Customizes recurring POST requests to the server.
|
||||
*/
|
||||
requestInit?: RequestInit;
|
||||
/**
|
||||
* Custom fetch implementation used for all network requests.
|
||||
*/
|
||||
fetch?: FetchLike;
|
||||
};
|
||||
/**
|
||||
* Client transport for SSE: this will connect to a server using Server-Sent Events for receiving
|
||||
* messages and make separate POST requests for sending messages.
|
||||
*/
|
||||
export declare class SSEClientTransport implements Transport {
|
||||
private _eventSource?;
|
||||
private _endpoint?;
|
||||
private _abortController?;
|
||||
private _url;
|
||||
private _resourceMetadataUrl?;
|
||||
private _eventSourceInit?;
|
||||
private _requestInit?;
|
||||
private _authProvider?;
|
||||
private _fetch?;
|
||||
private _protocolVersion?;
|
||||
onclose?: () => void;
|
||||
onerror?: (error: Error) => void;
|
||||
onmessage?: (message: JSONRPCMessage) => void;
|
||||
constructor(url: URL, opts?: SSEClientTransportOptions);
|
||||
private _authThenStart;
|
||||
private _commonHeaders;
|
||||
private _startOrAuth;
|
||||
start(): Promise<void>;
|
||||
/**
|
||||
* Call this method after the user has finished authorizing via their user agent and is redirected back to the MCP client application. This will exchange the authorization code for an access token, enabling the next connection attempt to successfully auth.
|
||||
*/
|
||||
finishAuth(authorizationCode: string): Promise<void>;
|
||||
close(): Promise<void>;
|
||||
send(message: JSONRPCMessage): Promise<void>;
|
||||
setProtocolVersion(version: string): void;
|
||||
}
|
||||
//# sourceMappingURL=sse.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/sse.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/sse.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../../src/client/sse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAwB,MAAM,aAAa,CAAC;AACnE,OAAO,EAAgD,mBAAmB,EAAqB,MAAM,WAAW,CAAC;AAEjH,qBAAa,QAAS,SAAQ,KAAK;aAEf,IAAI,EAAE,MAAM,GAAG,SAAS;aAExB,KAAK,EAAE,UAAU;gBAFjB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxC,OAAO,EAAE,MAAM,GAAG,SAAS,EACX,KAAK,EAAE,UAAU;CAIpC;AAED;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAEnC;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAElC;;OAEG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,SAAS;IAClD,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,SAAS,CAAC,CAAM;IACxB,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAC3C,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,oBAAoB,CAAC,CAAM;IACnC,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAC3C,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,aAAa,CAAC,CAAsB;IAC5C,OAAO,CAAC,MAAM,CAAC,CAAY;IAC3B,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAElC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;gBAG5C,GAAG,EAAE,GAAG,EACR,IAAI,CAAC,EAAE,yBAAyB;YAUpB,cAAc;YAoBd,cAAc;IAiB5B,OAAO,CAAC,YAAY;IA+Ed,KAAK;IAUX;;OAEG;IACG,UAAU,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA2ClD,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAG1C"}
|
||||
194
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/sse.js
generated
vendored
Normal file
194
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/sse.js
generated
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SSEClientTransport = exports.SseError = void 0;
|
||||
const eventsource_1 = require("eventsource");
|
||||
const types_js_1 = require("../types.js");
|
||||
const auth_js_1 = require("./auth.js");
|
||||
class SseError extends Error {
|
||||
constructor(code, message, event) {
|
||||
super(`SSE error: ${message}`);
|
||||
this.code = code;
|
||||
this.event = event;
|
||||
}
|
||||
}
|
||||
exports.SseError = SseError;
|
||||
/**
|
||||
* Client transport for SSE: this will connect to a server using Server-Sent Events for receiving
|
||||
* messages and make separate POST requests for sending messages.
|
||||
*/
|
||||
class SSEClientTransport {
|
||||
constructor(url, opts) {
|
||||
this._url = url;
|
||||
this._resourceMetadataUrl = undefined;
|
||||
this._eventSourceInit = opts === null || opts === void 0 ? void 0 : opts.eventSourceInit;
|
||||
this._requestInit = opts === null || opts === void 0 ? void 0 : opts.requestInit;
|
||||
this._authProvider = opts === null || opts === void 0 ? void 0 : opts.authProvider;
|
||||
this._fetch = opts === null || opts === void 0 ? void 0 : opts.fetch;
|
||||
}
|
||||
async _authThenStart() {
|
||||
var _a;
|
||||
if (!this._authProvider) {
|
||||
throw new auth_js_1.UnauthorizedError("No auth provider");
|
||||
}
|
||||
let result;
|
||||
try {
|
||||
result = await (0, auth_js_1.auth)(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
|
||||
}
|
||||
catch (error) {
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
||||
throw error;
|
||||
}
|
||||
if (result !== "AUTHORIZED") {
|
||||
throw new auth_js_1.UnauthorizedError();
|
||||
}
|
||||
return await this._startOrAuth();
|
||||
}
|
||||
async _commonHeaders() {
|
||||
var _a;
|
||||
const headers = {
|
||||
...(_a = this._requestInit) === null || _a === void 0 ? void 0 : _a.headers,
|
||||
};
|
||||
if (this._authProvider) {
|
||||
const tokens = await this._authProvider.tokens();
|
||||
if (tokens) {
|
||||
headers["Authorization"] = `Bearer ${tokens.access_token}`;
|
||||
}
|
||||
}
|
||||
if (this._protocolVersion) {
|
||||
headers["mcp-protocol-version"] = this._protocolVersion;
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
_startOrAuth() {
|
||||
var _a, _b, _c;
|
||||
const fetchImpl = ((_c = (_b = (_a = this === null || this === void 0 ? void 0 : this._eventSourceInit) === null || _a === void 0 ? void 0 : _a.fetch) !== null && _b !== void 0 ? _b : this._fetch) !== null && _c !== void 0 ? _c : fetch);
|
||||
return new Promise((resolve, reject) => {
|
||||
this._eventSource = new eventsource_1.EventSource(this._url.href, {
|
||||
...this._eventSourceInit,
|
||||
fetch: async (url, init) => {
|
||||
const headers = await this._commonHeaders();
|
||||
const response = await fetchImpl(url, {
|
||||
...init,
|
||||
headers: new Headers({
|
||||
...headers,
|
||||
Accept: "text/event-stream"
|
||||
})
|
||||
});
|
||||
if (response.status === 401 && response.headers.has('www-authenticate')) {
|
||||
this._resourceMetadataUrl = (0, auth_js_1.extractResourceMetadataUrl)(response);
|
||||
}
|
||||
return response;
|
||||
},
|
||||
});
|
||||
this._abortController = new AbortController();
|
||||
this._eventSource.onerror = (event) => {
|
||||
var _a;
|
||||
if (event.code === 401 && this._authProvider) {
|
||||
this._authThenStart().then(resolve, reject);
|
||||
return;
|
||||
}
|
||||
const error = new SseError(event.code, event.message, event);
|
||||
reject(error);
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
||||
};
|
||||
this._eventSource.onopen = () => {
|
||||
// The connection is open, but we need to wait for the endpoint to be received.
|
||||
};
|
||||
this._eventSource.addEventListener("endpoint", (event) => {
|
||||
var _a;
|
||||
const messageEvent = event;
|
||||
try {
|
||||
this._endpoint = new URL(messageEvent.data, this._url);
|
||||
if (this._endpoint.origin !== this._url.origin) {
|
||||
throw new Error(`Endpoint origin does not match connection origin: ${this._endpoint.origin}`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
reject(error);
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
||||
void this.close();
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
this._eventSource.onmessage = (event) => {
|
||||
var _a, _b;
|
||||
const messageEvent = event;
|
||||
let message;
|
||||
try {
|
||||
message = types_js_1.JSONRPCMessageSchema.parse(JSON.parse(messageEvent.data));
|
||||
}
|
||||
catch (error) {
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
||||
return;
|
||||
}
|
||||
(_b = this.onmessage) === null || _b === void 0 ? void 0 : _b.call(this, message);
|
||||
};
|
||||
});
|
||||
}
|
||||
async start() {
|
||||
if (this._eventSource) {
|
||||
throw new Error("SSEClientTransport already started! If using Client class, note that connect() calls start() automatically.");
|
||||
}
|
||||
return await this._startOrAuth();
|
||||
}
|
||||
/**
|
||||
* Call this method after the user has finished authorizing via their user agent and is redirected back to the MCP client application. This will exchange the authorization code for an access token, enabling the next connection attempt to successfully auth.
|
||||
*/
|
||||
async finishAuth(authorizationCode) {
|
||||
if (!this._authProvider) {
|
||||
throw new auth_js_1.UnauthorizedError("No auth provider");
|
||||
}
|
||||
const result = await (0, auth_js_1.auth)(this._authProvider, { serverUrl: this._url, authorizationCode, resourceMetadataUrl: this._resourceMetadataUrl });
|
||||
if (result !== "AUTHORIZED") {
|
||||
throw new auth_js_1.UnauthorizedError("Failed to authorize");
|
||||
}
|
||||
}
|
||||
async close() {
|
||||
var _a, _b, _c;
|
||||
(_a = this._abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
||||
(_b = this._eventSource) === null || _b === void 0 ? void 0 : _b.close();
|
||||
(_c = this.onclose) === null || _c === void 0 ? void 0 : _c.call(this);
|
||||
}
|
||||
async send(message) {
|
||||
var _a, _b, _c;
|
||||
if (!this._endpoint) {
|
||||
throw new Error("Not connected");
|
||||
}
|
||||
try {
|
||||
const commonHeaders = await this._commonHeaders();
|
||||
const headers = new Headers(commonHeaders);
|
||||
headers.set("content-type", "application/json");
|
||||
const init = {
|
||||
...this._requestInit,
|
||||
method: "POST",
|
||||
headers,
|
||||
body: JSON.stringify(message),
|
||||
signal: (_a = this._abortController) === null || _a === void 0 ? void 0 : _a.signal,
|
||||
};
|
||||
const response = await ((_b = this._fetch) !== null && _b !== void 0 ? _b : fetch)(this._endpoint, init);
|
||||
if (!response.ok) {
|
||||
if (response.status === 401 && this._authProvider) {
|
||||
this._resourceMetadataUrl = (0, auth_js_1.extractResourceMetadataUrl)(response);
|
||||
const result = await (0, auth_js_1.auth)(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
|
||||
if (result !== "AUTHORIZED") {
|
||||
throw new auth_js_1.UnauthorizedError();
|
||||
}
|
||||
// Purposely _not_ awaited, so we don't call onerror twice
|
||||
return this.send(message);
|
||||
}
|
||||
const text = await response.text().catch(() => null);
|
||||
throw new Error(`Error POSTing to endpoint (HTTP ${response.status}): ${text}`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
(_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
setProtocolVersion(version) {
|
||||
this._protocolVersion = version;
|
||||
}
|
||||
}
|
||||
exports.SSEClientTransport = SSEClientTransport;
|
||||
//# sourceMappingURL=sse.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/sse.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/sse.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
78
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.d.ts
generated
vendored
Normal file
78
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.d.ts
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
import { IOType } from "node:child_process";
|
||||
import { Stream } from "node:stream";
|
||||
import { Transport } from "../shared/transport.js";
|
||||
import { JSONRPCMessage } from "../types.js";
|
||||
export type StdioServerParameters = {
|
||||
/**
|
||||
* The executable to run to start the server.
|
||||
*/
|
||||
command: string;
|
||||
/**
|
||||
* Command line arguments to pass to the executable.
|
||||
*/
|
||||
args?: string[];
|
||||
/**
|
||||
* The environment to use when spawning the process.
|
||||
*
|
||||
* If not specified, the result of getDefaultEnvironment() will be used.
|
||||
*/
|
||||
env?: Record<string, string>;
|
||||
/**
|
||||
* How to handle stderr of the child process. This matches the semantics of Node's `child_process.spawn`.
|
||||
*
|
||||
* The default is "inherit", meaning messages to stderr will be printed to the parent process's stderr.
|
||||
*/
|
||||
stderr?: IOType | Stream | number;
|
||||
/**
|
||||
* The working directory to use when spawning the process.
|
||||
*
|
||||
* If not specified, the current working directory will be inherited.
|
||||
*/
|
||||
cwd?: string;
|
||||
};
|
||||
/**
|
||||
* Environment variables to inherit by default, if an environment is not explicitly given.
|
||||
*/
|
||||
export declare const DEFAULT_INHERITED_ENV_VARS: string[];
|
||||
/**
|
||||
* Returns a default environment object including only environment variables deemed safe to inherit.
|
||||
*/
|
||||
export declare function getDefaultEnvironment(): Record<string, string>;
|
||||
/**
|
||||
* Client transport for stdio: this will connect to a server by spawning a process and communicating with it over stdin/stdout.
|
||||
*
|
||||
* This transport is only available in Node.js environments.
|
||||
*/
|
||||
export declare class StdioClientTransport implements Transport {
|
||||
private _process?;
|
||||
private _abortController;
|
||||
private _readBuffer;
|
||||
private _serverParams;
|
||||
private _stderrStream;
|
||||
onclose?: () => void;
|
||||
onerror?: (error: Error) => void;
|
||||
onmessage?: (message: JSONRPCMessage) => void;
|
||||
constructor(server: StdioServerParameters);
|
||||
/**
|
||||
* Starts the server process and prepares to communicate with it.
|
||||
*/
|
||||
start(): Promise<void>;
|
||||
/**
|
||||
* The stderr stream of the child process, if `StdioServerParameters.stderr` was set to "pipe" or "overlapped".
|
||||
*
|
||||
* If stderr piping was requested, a PassThrough stream is returned _immediately_, allowing callers to
|
||||
* attach listeners before the start method is invoked. This prevents loss of any early
|
||||
* error output emitted by the child process.
|
||||
*/
|
||||
get stderr(): Stream | null;
|
||||
/**
|
||||
* The child process pid spawned by this transport.
|
||||
*
|
||||
* This is only available after the transport has been started.
|
||||
*/
|
||||
get pid(): number | null;
|
||||
private processReadBuffer;
|
||||
close(): Promise<void>;
|
||||
send(message: JSONRPCMessage): Promise<void>;
|
||||
}
|
||||
//# sourceMappingURL=stdio.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../src/client/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG1D,OAAO,EAAE,MAAM,EAAe,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7B;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAElC;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,UAiBmB,CAAC;AAE3D;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkB9D;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,YAAW,SAAS;IACpD,OAAO,CAAC,QAAQ,CAAC,CAAe;IAChC,OAAO,CAAC,gBAAgB,CAA0C;IAClE,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,aAAa,CAA4B;IAEjD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;gBAElC,MAAM,EAAE,qBAAqB;IAOzC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA4D5B;;;;;;OAMG;IACH,IAAI,MAAM,IAAI,MAAM,GAAG,IAAI,CAM1B;IAED;;;;OAIG;IACH,IAAI,GAAG,IAAI,MAAM,GAAG,IAAI,CAEvB;IAED,OAAO,CAAC,iBAAiB;IAenB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAc7C"}
|
||||
180
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.js
generated
vendored
Normal file
180
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.js
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.StdioClientTransport = exports.DEFAULT_INHERITED_ENV_VARS = void 0;
|
||||
exports.getDefaultEnvironment = getDefaultEnvironment;
|
||||
const cross_spawn_1 = __importDefault(require("cross-spawn"));
|
||||
const node_process_1 = __importDefault(require("node:process"));
|
||||
const node_stream_1 = require("node:stream");
|
||||
const stdio_js_1 = require("../shared/stdio.js");
|
||||
/**
|
||||
* Environment variables to inherit by default, if an environment is not explicitly given.
|
||||
*/
|
||||
exports.DEFAULT_INHERITED_ENV_VARS = node_process_1.default.platform === "win32"
|
||||
? [
|
||||
"APPDATA",
|
||||
"HOMEDRIVE",
|
||||
"HOMEPATH",
|
||||
"LOCALAPPDATA",
|
||||
"PATH",
|
||||
"PROCESSOR_ARCHITECTURE",
|
||||
"SYSTEMDRIVE",
|
||||
"SYSTEMROOT",
|
||||
"TEMP",
|
||||
"USERNAME",
|
||||
"USERPROFILE",
|
||||
"PROGRAMFILES",
|
||||
]
|
||||
: /* list inspired by the default env inheritance of sudo */
|
||||
["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER"];
|
||||
/**
|
||||
* Returns a default environment object including only environment variables deemed safe to inherit.
|
||||
*/
|
||||
function getDefaultEnvironment() {
|
||||
const env = {};
|
||||
for (const key of exports.DEFAULT_INHERITED_ENV_VARS) {
|
||||
const value = node_process_1.default.env[key];
|
||||
if (value === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (value.startsWith("()")) {
|
||||
// Skip functions, which are a security risk.
|
||||
continue;
|
||||
}
|
||||
env[key] = value;
|
||||
}
|
||||
return env;
|
||||
}
|
||||
/**
|
||||
* Client transport for stdio: this will connect to a server by spawning a process and communicating with it over stdin/stdout.
|
||||
*
|
||||
* This transport is only available in Node.js environments.
|
||||
*/
|
||||
class StdioClientTransport {
|
||||
constructor(server) {
|
||||
this._abortController = new AbortController();
|
||||
this._readBuffer = new stdio_js_1.ReadBuffer();
|
||||
this._stderrStream = null;
|
||||
this._serverParams = server;
|
||||
if (server.stderr === "pipe" || server.stderr === "overlapped") {
|
||||
this._stderrStream = new node_stream_1.PassThrough();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Starts the server process and prepares to communicate with it.
|
||||
*/
|
||||
async start() {
|
||||
if (this._process) {
|
||||
throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
this._process = (0, cross_spawn_1.default)(this._serverParams.command, (_a = this._serverParams.args) !== null && _a !== void 0 ? _a : [], {
|
||||
env: (_b = this._serverParams.env) !== null && _b !== void 0 ? _b : getDefaultEnvironment(),
|
||||
stdio: ["pipe", "pipe", (_c = this._serverParams.stderr) !== null && _c !== void 0 ? _c : "inherit"],
|
||||
shell: false,
|
||||
signal: this._abortController.signal,
|
||||
windowsHide: node_process_1.default.platform === "win32" && isElectron(),
|
||||
cwd: this._serverParams.cwd,
|
||||
});
|
||||
this._process.on("error", (error) => {
|
||||
var _a, _b;
|
||||
if (error.name === "AbortError") {
|
||||
// Expected when close() is called.
|
||||
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
|
||||
return;
|
||||
}
|
||||
reject(error);
|
||||
(_b = this.onerror) === null || _b === void 0 ? void 0 : _b.call(this, error);
|
||||
});
|
||||
this._process.on("spawn", () => {
|
||||
resolve();
|
||||
});
|
||||
this._process.on("close", (_code) => {
|
||||
var _a;
|
||||
this._process = undefined;
|
||||
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
|
||||
});
|
||||
(_d = this._process.stdin) === null || _d === void 0 ? void 0 : _d.on("error", (error) => {
|
||||
var _a;
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
||||
});
|
||||
(_e = this._process.stdout) === null || _e === void 0 ? void 0 : _e.on("data", (chunk) => {
|
||||
this._readBuffer.append(chunk);
|
||||
this.processReadBuffer();
|
||||
});
|
||||
(_f = this._process.stdout) === null || _f === void 0 ? void 0 : _f.on("error", (error) => {
|
||||
var _a;
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
||||
});
|
||||
if (this._stderrStream && this._process.stderr) {
|
||||
this._process.stderr.pipe(this._stderrStream);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* The stderr stream of the child process, if `StdioServerParameters.stderr` was set to "pipe" or "overlapped".
|
||||
*
|
||||
* If stderr piping was requested, a PassThrough stream is returned _immediately_, allowing callers to
|
||||
* attach listeners before the start method is invoked. This prevents loss of any early
|
||||
* error output emitted by the child process.
|
||||
*/
|
||||
get stderr() {
|
||||
var _a, _b;
|
||||
if (this._stderrStream) {
|
||||
return this._stderrStream;
|
||||
}
|
||||
return (_b = (_a = this._process) === null || _a === void 0 ? void 0 : _a.stderr) !== null && _b !== void 0 ? _b : null;
|
||||
}
|
||||
/**
|
||||
* The child process pid spawned by this transport.
|
||||
*
|
||||
* This is only available after the transport has been started.
|
||||
*/
|
||||
get pid() {
|
||||
var _a, _b;
|
||||
return (_b = (_a = this._process) === null || _a === void 0 ? void 0 : _a.pid) !== null && _b !== void 0 ? _b : null;
|
||||
}
|
||||
processReadBuffer() {
|
||||
var _a, _b;
|
||||
while (true) {
|
||||
try {
|
||||
const message = this._readBuffer.readMessage();
|
||||
if (message === null) {
|
||||
break;
|
||||
}
|
||||
(_a = this.onmessage) === null || _a === void 0 ? void 0 : _a.call(this, message);
|
||||
}
|
||||
catch (error) {
|
||||
(_b = this.onerror) === null || _b === void 0 ? void 0 : _b.call(this, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
async close() {
|
||||
this._abortController.abort();
|
||||
this._process = undefined;
|
||||
this._readBuffer.clear();
|
||||
}
|
||||
send(message) {
|
||||
return new Promise((resolve) => {
|
||||
var _a;
|
||||
if (!((_a = this._process) === null || _a === void 0 ? void 0 : _a.stdin)) {
|
||||
throw new Error("Not connected");
|
||||
}
|
||||
const json = (0, stdio_js_1.serializeMessage)(message);
|
||||
if (this._process.stdin.write(json)) {
|
||||
resolve();
|
||||
}
|
||||
else {
|
||||
this._process.stdin.once("drain", resolve);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.StdioClientTransport = StdioClientTransport;
|
||||
function isElectron() {
|
||||
return "type" in node_process_1.default;
|
||||
}
|
||||
//# sourceMappingURL=stdio.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../../src/client/stdio.ts"],"names":[],"mappings":"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"}
|
||||
156
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.d.ts
generated
vendored
Normal file
156
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.d.ts
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
import { Transport, FetchLike } from "../shared/transport.js";
|
||||
import { JSONRPCMessage } from "../types.js";
|
||||
import { OAuthClientProvider } from "./auth.js";
|
||||
export declare class StreamableHTTPError extends Error {
|
||||
readonly code: number | undefined;
|
||||
constructor(code: number | undefined, message: string | undefined);
|
||||
}
|
||||
/**
|
||||
* Options for starting or authenticating an SSE connection
|
||||
*/
|
||||
export interface StartSSEOptions {
|
||||
/**
|
||||
* The resumption token used to continue long-running requests that were interrupted.
|
||||
*
|
||||
* This allows clients to reconnect and continue from where they left off.
|
||||
*/
|
||||
resumptionToken?: string;
|
||||
/**
|
||||
* A callback that is invoked when the resumption token changes.
|
||||
*
|
||||
* This allows clients to persist the latest token for potential reconnection.
|
||||
*/
|
||||
onresumptiontoken?: (token: string) => void;
|
||||
/**
|
||||
* Override Message ID to associate with the replay message
|
||||
* so that response can be associate with the new resumed request.
|
||||
*/
|
||||
replayMessageId?: string | number;
|
||||
}
|
||||
/**
|
||||
* Configuration options for reconnection behavior of the StreamableHTTPClientTransport.
|
||||
*/
|
||||
export interface StreamableHTTPReconnectionOptions {
|
||||
/**
|
||||
* Maximum backoff time between reconnection attempts in milliseconds.
|
||||
* Default is 30000 (30 seconds).
|
||||
*/
|
||||
maxReconnectionDelay: number;
|
||||
/**
|
||||
* Initial backoff time between reconnection attempts in milliseconds.
|
||||
* Default is 1000 (1 second).
|
||||
*/
|
||||
initialReconnectionDelay: number;
|
||||
/**
|
||||
* The factor by which the reconnection delay increases after each attempt.
|
||||
* Default is 1.5.
|
||||
*/
|
||||
reconnectionDelayGrowFactor: number;
|
||||
/**
|
||||
* Maximum number of reconnection attempts before giving up.
|
||||
* Default is 2.
|
||||
*/
|
||||
maxRetries: number;
|
||||
}
|
||||
/**
|
||||
* Configuration options for the `StreamableHTTPClientTransport`.
|
||||
*/
|
||||
export type StreamableHTTPClientTransportOptions = {
|
||||
/**
|
||||
* An OAuth client provider to use for authentication.
|
||||
*
|
||||
* When an `authProvider` is specified and the connection is started:
|
||||
* 1. The connection is attempted with any existing access token from the `authProvider`.
|
||||
* 2. If the access token has expired, the `authProvider` is used to refresh the token.
|
||||
* 3. If token refresh fails or no access token exists, and auth is required, `OAuthClientProvider.redirectToAuthorization` is called, and an `UnauthorizedError` will be thrown from `connect`/`start`.
|
||||
*
|
||||
* After the user has finished authorizing via their user agent, and is redirected back to the MCP client application, call `StreamableHTTPClientTransport.finishAuth` with the authorization code before retrying the connection.
|
||||
*
|
||||
* If an `authProvider` is not provided, and auth is required, an `UnauthorizedError` will be thrown.
|
||||
*
|
||||
* `UnauthorizedError` might also be thrown when sending any message over the transport, indicating that the session has expired, and needs to be re-authed and reconnected.
|
||||
*/
|
||||
authProvider?: OAuthClientProvider;
|
||||
/**
|
||||
* Customizes HTTP requests to the server.
|
||||
*/
|
||||
requestInit?: RequestInit;
|
||||
/**
|
||||
* Custom fetch implementation used for all network requests.
|
||||
*/
|
||||
fetch?: FetchLike;
|
||||
/**
|
||||
* Options to configure the reconnection behavior.
|
||||
*/
|
||||
reconnectionOptions?: StreamableHTTPReconnectionOptions;
|
||||
/**
|
||||
* Session ID for the connection. This is used to identify the session on the server.
|
||||
* When not provided and connecting to a server that supports session IDs, the server will generate a new session ID.
|
||||
*/
|
||||
sessionId?: string;
|
||||
};
|
||||
/**
|
||||
* Client transport for Streamable HTTP: this implements the MCP Streamable HTTP transport specification.
|
||||
* It will connect to a server using HTTP POST for sending messages and HTTP GET with Server-Sent Events
|
||||
* for receiving messages.
|
||||
*/
|
||||
export declare class StreamableHTTPClientTransport implements Transport {
|
||||
private _abortController?;
|
||||
private _url;
|
||||
private _resourceMetadataUrl?;
|
||||
private _requestInit?;
|
||||
private _authProvider?;
|
||||
private _fetch?;
|
||||
private _sessionId?;
|
||||
private _reconnectionOptions;
|
||||
private _protocolVersion?;
|
||||
onclose?: () => void;
|
||||
onerror?: (error: Error) => void;
|
||||
onmessage?: (message: JSONRPCMessage) => void;
|
||||
constructor(url: URL, opts?: StreamableHTTPClientTransportOptions);
|
||||
private _authThenStart;
|
||||
private _commonHeaders;
|
||||
private _startOrAuthSse;
|
||||
/**
|
||||
* Calculates the next reconnection delay using backoff algorithm
|
||||
*
|
||||
* @param attempt Current reconnection attempt count for the specific stream
|
||||
* @returns Time to wait in milliseconds before next reconnection attempt
|
||||
*/
|
||||
private _getNextReconnectionDelay;
|
||||
private _normalizeHeaders;
|
||||
/**
|
||||
* Schedule a reconnection attempt with exponential backoff
|
||||
*
|
||||
* @param lastEventId The ID of the last received event for resumability
|
||||
* @param attemptCount Current reconnection attempt count for this specific stream
|
||||
*/
|
||||
private _scheduleReconnection;
|
||||
private _handleSseStream;
|
||||
start(): Promise<void>;
|
||||
/**
|
||||
* Call this method after the user has finished authorizing via their user agent and is redirected back to the MCP client application. This will exchange the authorization code for an access token, enabling the next connection attempt to successfully auth.
|
||||
*/
|
||||
finishAuth(authorizationCode: string): Promise<void>;
|
||||
close(): Promise<void>;
|
||||
send(message: JSONRPCMessage | JSONRPCMessage[], options?: {
|
||||
resumptionToken?: string;
|
||||
onresumptiontoken?: (token: string) => void;
|
||||
}): Promise<void>;
|
||||
get sessionId(): string | undefined;
|
||||
/**
|
||||
* Terminates the current session by sending a DELETE request to the server.
|
||||
*
|
||||
* Clients that no longer need a particular session
|
||||
* (e.g., because the user is leaving the client application) SHOULD send an
|
||||
* HTTP DELETE to the MCP endpoint with the Mcp-Session-Id header to explicitly
|
||||
* terminate the session.
|
||||
*
|
||||
* The server MAY respond with HTTP 405 Method Not Allowed, indicating that
|
||||
* the server does not allow clients to terminate sessions.
|
||||
*/
|
||||
terminateSession(): Promise<void>;
|
||||
setProtocolVersion(version: string): void;
|
||||
get protocolVersion(): string | undefined;
|
||||
}
|
||||
//# sourceMappingURL=streamableHttp.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"streamableHttp.d.ts","sourceRoot":"","sources":["../../../src/client/streamableHttp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAkE,cAAc,EAAwB,MAAM,aAAa,CAAC;AACnI,OAAO,EAAgD,mBAAmB,EAAqB,MAAM,WAAW,CAAC;AAWjH,qBAAa,mBAAoB,SAAQ,KAAK;aAE1B,IAAI,EAAE,MAAM,GAAG,SAAS;gBAAxB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxC,OAAO,EAAE,MAAM,GAAG,SAAS;CAI9B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAE5C;;;MAGE;IACF,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,iCAAiC;IAChD;;;OAGG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,wBAAwB,EAAE,MAAM,CAAC;IAEjC;;;OAGG;IACH,2BAA2B,EAAE,MAAM,CAAC;IAEpC;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,oCAAoC,GAAG;IACjD;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAEnC;;OAEG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB;;OAEG;IACH,mBAAmB,CAAC,EAAE,iCAAiC,CAAC;IAExD;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,qBAAa,6BAA8B,YAAW,SAAS;IAC7D,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAC3C,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,oBAAoB,CAAC,CAAM;IACnC,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,aAAa,CAAC,CAAsB;IAC5C,OAAO,CAAC,MAAM,CAAC,CAAY;IAC3B,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,oBAAoB,CAAoC;IAChE,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAElC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;gBAG5C,GAAG,EAAE,GAAG,EACR,IAAI,CAAC,EAAE,oCAAoC;YAW/B,cAAc;YAoBd,cAAc;YAyBd,eAAe;IA6C7B;;;;;OAKG;IACH,OAAO,CAAC,yBAAyB;IAW/B,OAAO,CAAC,iBAAiB;IAc3B;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAwB7B,OAAO,CAAC,gBAAgB;IAoElB,KAAK;IAUX;;OAEG;IACG,UAAU,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,EAAE,EAAE,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAkG1J,IAAI,SAAS,IAAI,MAAM,GAAG,SAAS,CAElC;IAED;;;;;;;;;;OAUG;IACG,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAiCvC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAGzC,IAAI,eAAe,IAAI,MAAM,GAAG,SAAS,CAExC;CACF"}
|
||||
380
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.js
generated
vendored
Normal file
380
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.js
generated
vendored
Normal file
@@ -0,0 +1,380 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.StreamableHTTPClientTransport = exports.StreamableHTTPError = void 0;
|
||||
const types_js_1 = require("../types.js");
|
||||
const auth_js_1 = require("./auth.js");
|
||||
const stream_1 = require("eventsource-parser/stream");
|
||||
// Default reconnection options for StreamableHTTP connections
|
||||
const DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS = {
|
||||
initialReconnectionDelay: 1000,
|
||||
maxReconnectionDelay: 30000,
|
||||
reconnectionDelayGrowFactor: 1.5,
|
||||
maxRetries: 2,
|
||||
};
|
||||
class StreamableHTTPError extends Error {
|
||||
constructor(code, message) {
|
||||
super(`Streamable HTTP error: ${message}`);
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
exports.StreamableHTTPError = StreamableHTTPError;
|
||||
/**
|
||||
* Client transport for Streamable HTTP: this implements the MCP Streamable HTTP transport specification.
|
||||
* It will connect to a server using HTTP POST for sending messages and HTTP GET with Server-Sent Events
|
||||
* for receiving messages.
|
||||
*/
|
||||
class StreamableHTTPClientTransport {
|
||||
constructor(url, opts) {
|
||||
var _a;
|
||||
this._url = url;
|
||||
this._resourceMetadataUrl = undefined;
|
||||
this._requestInit = opts === null || opts === void 0 ? void 0 : opts.requestInit;
|
||||
this._authProvider = opts === null || opts === void 0 ? void 0 : opts.authProvider;
|
||||
this._fetch = opts === null || opts === void 0 ? void 0 : opts.fetch;
|
||||
this._sessionId = opts === null || opts === void 0 ? void 0 : opts.sessionId;
|
||||
this._reconnectionOptions = (_a = opts === null || opts === void 0 ? void 0 : opts.reconnectionOptions) !== null && _a !== void 0 ? _a : DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS;
|
||||
}
|
||||
async _authThenStart() {
|
||||
var _a;
|
||||
if (!this._authProvider) {
|
||||
throw new auth_js_1.UnauthorizedError("No auth provider");
|
||||
}
|
||||
let result;
|
||||
try {
|
||||
result = await (0, auth_js_1.auth)(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
|
||||
}
|
||||
catch (error) {
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
||||
throw error;
|
||||
}
|
||||
if (result !== "AUTHORIZED") {
|
||||
throw new auth_js_1.UnauthorizedError();
|
||||
}
|
||||
return await this._startOrAuthSse({ resumptionToken: undefined });
|
||||
}
|
||||
async _commonHeaders() {
|
||||
var _a;
|
||||
const headers = {};
|
||||
if (this._authProvider) {
|
||||
const tokens = await this._authProvider.tokens();
|
||||
if (tokens) {
|
||||
headers["Authorization"] = `Bearer ${tokens.access_token}`;
|
||||
}
|
||||
}
|
||||
if (this._sessionId) {
|
||||
headers["mcp-session-id"] = this._sessionId;
|
||||
}
|
||||
if (this._protocolVersion) {
|
||||
headers["mcp-protocol-version"] = this._protocolVersion;
|
||||
}
|
||||
const extraHeaders = this._normalizeHeaders((_a = this._requestInit) === null || _a === void 0 ? void 0 : _a.headers);
|
||||
return new Headers({
|
||||
...headers,
|
||||
...extraHeaders,
|
||||
});
|
||||
}
|
||||
async _startOrAuthSse(options) {
|
||||
var _a, _b, _c;
|
||||
const { resumptionToken } = options;
|
||||
try {
|
||||
// Try to open an initial SSE stream with GET to listen for server messages
|
||||
// This is optional according to the spec - server may not support it
|
||||
const headers = await this._commonHeaders();
|
||||
headers.set("Accept", "text/event-stream");
|
||||
// Include Last-Event-ID header for resumable streams if provided
|
||||
if (resumptionToken) {
|
||||
headers.set("last-event-id", resumptionToken);
|
||||
}
|
||||
const response = await ((_a = this._fetch) !== null && _a !== void 0 ? _a : fetch)(this._url, {
|
||||
method: "GET",
|
||||
headers,
|
||||
signal: (_b = this._abortController) === null || _b === void 0 ? void 0 : _b.signal,
|
||||
});
|
||||
if (!response.ok) {
|
||||
if (response.status === 401 && this._authProvider) {
|
||||
// Need to authenticate
|
||||
return await this._authThenStart();
|
||||
}
|
||||
// 405 indicates that the server does not offer an SSE stream at GET endpoint
|
||||
// This is an expected case that should not trigger an error
|
||||
if (response.status === 405) {
|
||||
return;
|
||||
}
|
||||
throw new StreamableHTTPError(response.status, `Failed to open SSE stream: ${response.statusText}`);
|
||||
}
|
||||
this._handleSseStream(response.body, options);
|
||||
}
|
||||
catch (error) {
|
||||
(_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Calculates the next reconnection delay using backoff algorithm
|
||||
*
|
||||
* @param attempt Current reconnection attempt count for the specific stream
|
||||
* @returns Time to wait in milliseconds before next reconnection attempt
|
||||
*/
|
||||
_getNextReconnectionDelay(attempt) {
|
||||
// Access default values directly, ensuring they're never undefined
|
||||
const initialDelay = this._reconnectionOptions.initialReconnectionDelay;
|
||||
const growFactor = this._reconnectionOptions.reconnectionDelayGrowFactor;
|
||||
const maxDelay = this._reconnectionOptions.maxReconnectionDelay;
|
||||
// Cap at maximum delay
|
||||
return Math.min(initialDelay * Math.pow(growFactor, attempt), maxDelay);
|
||||
}
|
||||
_normalizeHeaders(headers) {
|
||||
if (!headers)
|
||||
return {};
|
||||
if (headers instanceof Headers) {
|
||||
return Object.fromEntries(headers.entries());
|
||||
}
|
||||
if (Array.isArray(headers)) {
|
||||
return Object.fromEntries(headers);
|
||||
}
|
||||
return { ...headers };
|
||||
}
|
||||
/**
|
||||
* Schedule a reconnection attempt with exponential backoff
|
||||
*
|
||||
* @param lastEventId The ID of the last received event for resumability
|
||||
* @param attemptCount Current reconnection attempt count for this specific stream
|
||||
*/
|
||||
_scheduleReconnection(options, attemptCount = 0) {
|
||||
var _a;
|
||||
// Use provided options or default options
|
||||
const maxRetries = this._reconnectionOptions.maxRetries;
|
||||
// Check if we've exceeded maximum retry attempts
|
||||
if (maxRetries > 0 && attemptCount >= maxRetries) {
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, new Error(`Maximum reconnection attempts (${maxRetries}) exceeded.`));
|
||||
return;
|
||||
}
|
||||
// Calculate next delay based on current attempt count
|
||||
const delay = this._getNextReconnectionDelay(attemptCount);
|
||||
// Schedule the reconnection
|
||||
setTimeout(() => {
|
||||
// Use the last event ID to resume where we left off
|
||||
this._startOrAuthSse(options).catch(error => {
|
||||
var _a;
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, new Error(`Failed to reconnect SSE stream: ${error instanceof Error ? error.message : String(error)}`));
|
||||
// Schedule another attempt if this one failed, incrementing the attempt counter
|
||||
this._scheduleReconnection(options, attemptCount + 1);
|
||||
});
|
||||
}, delay);
|
||||
}
|
||||
_handleSseStream(stream, options) {
|
||||
if (!stream) {
|
||||
return;
|
||||
}
|
||||
const { onresumptiontoken, replayMessageId } = options;
|
||||
let lastEventId;
|
||||
const processStream = async () => {
|
||||
var _a, _b, _c, _d;
|
||||
// this is the closest we can get to trying to catch network errors
|
||||
// if something happens reader will throw
|
||||
try {
|
||||
// Create a pipeline: binary stream -> text decoder -> SSE parser
|
||||
const reader = stream
|
||||
.pipeThrough(new TextDecoderStream())
|
||||
.pipeThrough(new stream_1.EventSourceParserStream())
|
||||
.getReader();
|
||||
while (true) {
|
||||
const { value: event, done } = await reader.read();
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
// Update last event ID if provided
|
||||
if (event.id) {
|
||||
lastEventId = event.id;
|
||||
onresumptiontoken === null || onresumptiontoken === void 0 ? void 0 : onresumptiontoken(event.id);
|
||||
}
|
||||
if (!event.event || event.event === "message") {
|
||||
try {
|
||||
const message = types_js_1.JSONRPCMessageSchema.parse(JSON.parse(event.data));
|
||||
if (replayMessageId !== undefined && (0, types_js_1.isJSONRPCResponse)(message)) {
|
||||
message.id = replayMessageId;
|
||||
}
|
||||
(_a = this.onmessage) === null || _a === void 0 ? void 0 : _a.call(this, message);
|
||||
}
|
||||
catch (error) {
|
||||
(_b = this.onerror) === null || _b === void 0 ? void 0 : _b.call(this, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
// Handle stream errors - likely a network disconnect
|
||||
(_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, new Error(`SSE stream disconnected: ${error}`));
|
||||
// Attempt to reconnect if the stream disconnects unexpectedly and we aren't closing
|
||||
if (this._abortController && !this._abortController.signal.aborted) {
|
||||
// Use the exponential backoff reconnection strategy
|
||||
if (lastEventId !== undefined) {
|
||||
try {
|
||||
this._scheduleReconnection({
|
||||
resumptionToken: lastEventId,
|
||||
onresumptiontoken,
|
||||
replayMessageId
|
||||
}, 0);
|
||||
}
|
||||
catch (error) {
|
||||
(_d = this.onerror) === null || _d === void 0 ? void 0 : _d.call(this, new Error(`Failed to reconnect: ${error instanceof Error ? error.message : String(error)}`));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
processStream();
|
||||
}
|
||||
async start() {
|
||||
if (this._abortController) {
|
||||
throw new Error("StreamableHTTPClientTransport already started! If using Client class, note that connect() calls start() automatically.");
|
||||
}
|
||||
this._abortController = new AbortController();
|
||||
}
|
||||
/**
|
||||
* Call this method after the user has finished authorizing via their user agent and is redirected back to the MCP client application. This will exchange the authorization code for an access token, enabling the next connection attempt to successfully auth.
|
||||
*/
|
||||
async finishAuth(authorizationCode) {
|
||||
if (!this._authProvider) {
|
||||
throw new auth_js_1.UnauthorizedError("No auth provider");
|
||||
}
|
||||
const result = await (0, auth_js_1.auth)(this._authProvider, { serverUrl: this._url, authorizationCode, resourceMetadataUrl: this._resourceMetadataUrl });
|
||||
if (result !== "AUTHORIZED") {
|
||||
throw new auth_js_1.UnauthorizedError("Failed to authorize");
|
||||
}
|
||||
}
|
||||
async close() {
|
||||
var _a, _b;
|
||||
// Abort any pending requests
|
||||
(_a = this._abortController) === null || _a === void 0 ? void 0 : _a.abort();
|
||||
(_b = this.onclose) === null || _b === void 0 ? void 0 : _b.call(this);
|
||||
}
|
||||
async send(message, options) {
|
||||
var _a, _b, _c, _d;
|
||||
try {
|
||||
const { resumptionToken, onresumptiontoken } = options || {};
|
||||
if (resumptionToken) {
|
||||
// If we have at last event ID, we need to reconnect the SSE stream
|
||||
this._startOrAuthSse({ resumptionToken, replayMessageId: (0, types_js_1.isJSONRPCRequest)(message) ? message.id : undefined }).catch(err => { var _a; return (_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, err); });
|
||||
return;
|
||||
}
|
||||
const headers = await this._commonHeaders();
|
||||
headers.set("content-type", "application/json");
|
||||
headers.set("accept", "application/json, text/event-stream");
|
||||
const init = {
|
||||
...this._requestInit,
|
||||
method: "POST",
|
||||
headers,
|
||||
body: JSON.stringify(message),
|
||||
signal: (_a = this._abortController) === null || _a === void 0 ? void 0 : _a.signal,
|
||||
};
|
||||
const response = await ((_b = this._fetch) !== null && _b !== void 0 ? _b : fetch)(this._url, init);
|
||||
// Handle session ID received during initialization
|
||||
const sessionId = response.headers.get("mcp-session-id");
|
||||
if (sessionId) {
|
||||
this._sessionId = sessionId;
|
||||
}
|
||||
if (!response.ok) {
|
||||
if (response.status === 401 && this._authProvider) {
|
||||
this._resourceMetadataUrl = (0, auth_js_1.extractResourceMetadataUrl)(response);
|
||||
const result = await (0, auth_js_1.auth)(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
|
||||
if (result !== "AUTHORIZED") {
|
||||
throw new auth_js_1.UnauthorizedError();
|
||||
}
|
||||
// Purposely _not_ awaited, so we don't call onerror twice
|
||||
return this.send(message);
|
||||
}
|
||||
const text = await response.text().catch(() => null);
|
||||
throw new Error(`Error POSTing to endpoint (HTTP ${response.status}): ${text}`);
|
||||
}
|
||||
// If the response is 202 Accepted, there's no body to process
|
||||
if (response.status === 202) {
|
||||
// if the accepted notification is initialized, we start the SSE stream
|
||||
// if it's supported by the server
|
||||
if ((0, types_js_1.isInitializedNotification)(message)) {
|
||||
// Start without a lastEventId since this is a fresh connection
|
||||
this._startOrAuthSse({ resumptionToken: undefined }).catch(err => { var _a; return (_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, err); });
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Get original message(s) for detecting request IDs
|
||||
const messages = Array.isArray(message) ? message : [message];
|
||||
const hasRequests = messages.filter(msg => "method" in msg && "id" in msg && msg.id !== undefined).length > 0;
|
||||
// Check the response type
|
||||
const contentType = response.headers.get("content-type");
|
||||
if (hasRequests) {
|
||||
if (contentType === null || contentType === void 0 ? void 0 : contentType.includes("text/event-stream")) {
|
||||
// Handle SSE stream responses for requests
|
||||
// We use the same handler as standalone streams, which now supports
|
||||
// reconnection with the last event ID
|
||||
this._handleSseStream(response.body, { onresumptiontoken });
|
||||
}
|
||||
else if (contentType === null || contentType === void 0 ? void 0 : contentType.includes("application/json")) {
|
||||
// For non-streaming servers, we might get direct JSON responses
|
||||
const data = await response.json();
|
||||
const responseMessages = Array.isArray(data)
|
||||
? data.map(msg => types_js_1.JSONRPCMessageSchema.parse(msg))
|
||||
: [types_js_1.JSONRPCMessageSchema.parse(data)];
|
||||
for (const msg of responseMessages) {
|
||||
(_c = this.onmessage) === null || _c === void 0 ? void 0 : _c.call(this, msg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new StreamableHTTPError(-1, `Unexpected content type: ${contentType}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
(_d = this.onerror) === null || _d === void 0 ? void 0 : _d.call(this, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
get sessionId() {
|
||||
return this._sessionId;
|
||||
}
|
||||
/**
|
||||
* Terminates the current session by sending a DELETE request to the server.
|
||||
*
|
||||
* Clients that no longer need a particular session
|
||||
* (e.g., because the user is leaving the client application) SHOULD send an
|
||||
* HTTP DELETE to the MCP endpoint with the Mcp-Session-Id header to explicitly
|
||||
* terminate the session.
|
||||
*
|
||||
* The server MAY respond with HTTP 405 Method Not Allowed, indicating that
|
||||
* the server does not allow clients to terminate sessions.
|
||||
*/
|
||||
async terminateSession() {
|
||||
var _a, _b, _c;
|
||||
if (!this._sessionId) {
|
||||
return; // No session to terminate
|
||||
}
|
||||
try {
|
||||
const headers = await this._commonHeaders();
|
||||
const init = {
|
||||
...this._requestInit,
|
||||
method: "DELETE",
|
||||
headers,
|
||||
signal: (_a = this._abortController) === null || _a === void 0 ? void 0 : _a.signal,
|
||||
};
|
||||
const response = await ((_b = this._fetch) !== null && _b !== void 0 ? _b : fetch)(this._url, init);
|
||||
// We specifically handle 405 as a valid response according to the spec,
|
||||
// meaning the server does not support explicit session termination
|
||||
if (!response.ok && response.status !== 405) {
|
||||
throw new StreamableHTTPError(response.status, `Failed to terminate session: ${response.statusText}`);
|
||||
}
|
||||
this._sessionId = undefined;
|
||||
}
|
||||
catch (error) {
|
||||
(_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
setProtocolVersion(version) {
|
||||
this._protocolVersion = version;
|
||||
}
|
||||
get protocolVersion() {
|
||||
return this._protocolVersion;
|
||||
}
|
||||
}
|
||||
exports.StreamableHTTPClientTransport = StreamableHTTPClientTransport;
|
||||
//# sourceMappingURL=streamableHttp.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
17
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/websocket.d.ts
generated
vendored
Normal file
17
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/websocket.d.ts
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Transport } from "../shared/transport.js";
|
||||
import { JSONRPCMessage } from "../types.js";
|
||||
/**
|
||||
* Client transport for WebSocket: this will connect to a server over the WebSocket protocol.
|
||||
*/
|
||||
export declare class WebSocketClientTransport implements Transport {
|
||||
private _socket?;
|
||||
private _url;
|
||||
onclose?: () => void;
|
||||
onerror?: (error: Error) => void;
|
||||
onmessage?: (message: JSONRPCMessage) => void;
|
||||
constructor(url: URL);
|
||||
start(): Promise<void>;
|
||||
close(): Promise<void>;
|
||||
send(message: JSONRPCMessage): Promise<void>;
|
||||
}
|
||||
//# sourceMappingURL=websocket.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/websocket.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/websocket.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../../src/client/websocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAwB,MAAM,aAAa,CAAC;AAInE;;GAEG;AACH,qBAAa,wBAAyB,YAAW,SAAS;IACxD,OAAO,CAAC,OAAO,CAAC,CAAY;IAC5B,OAAO,CAAC,IAAI,CAAM;IAElB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;gBAElC,GAAG,EAAE,GAAG;IAIpB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyChB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAW7C"}
|
||||
65
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/websocket.js
generated
vendored
Normal file
65
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/websocket.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WebSocketClientTransport = void 0;
|
||||
const types_js_1 = require("../types.js");
|
||||
const SUBPROTOCOL = "mcp";
|
||||
/**
|
||||
* Client transport for WebSocket: this will connect to a server over the WebSocket protocol.
|
||||
*/
|
||||
class WebSocketClientTransport {
|
||||
constructor(url) {
|
||||
this._url = url;
|
||||
}
|
||||
start() {
|
||||
if (this._socket) {
|
||||
throw new Error("WebSocketClientTransport already started! If using Client class, note that connect() calls start() automatically.");
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._socket = new WebSocket(this._url, SUBPROTOCOL);
|
||||
this._socket.onerror = (event) => {
|
||||
var _a;
|
||||
const error = "error" in event
|
||||
? event.error
|
||||
: new Error(`WebSocket error: ${JSON.stringify(event)}`);
|
||||
reject(error);
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
||||
};
|
||||
this._socket.onopen = () => {
|
||||
resolve();
|
||||
};
|
||||
this._socket.onclose = () => {
|
||||
var _a;
|
||||
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
|
||||
};
|
||||
this._socket.onmessage = (event) => {
|
||||
var _a, _b;
|
||||
let message;
|
||||
try {
|
||||
message = types_js_1.JSONRPCMessageSchema.parse(JSON.parse(event.data));
|
||||
}
|
||||
catch (error) {
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
||||
return;
|
||||
}
|
||||
(_b = this.onmessage) === null || _b === void 0 ? void 0 : _b.call(this, message);
|
||||
};
|
||||
});
|
||||
}
|
||||
async close() {
|
||||
var _a;
|
||||
(_a = this._socket) === null || _a === void 0 ? void 0 : _a.close();
|
||||
}
|
||||
send(message) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var _a;
|
||||
if (!this._socket) {
|
||||
reject(new Error("Not connected"));
|
||||
return;
|
||||
}
|
||||
(_a = this._socket) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify(message));
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.WebSocketClientTransport = WebSocketClientTransport;
|
||||
//# sourceMappingURL=websocket.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/websocket.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/websocket.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../../src/client/websocket.ts"],"names":[],"mappings":";;;AACA,0CAAmE;AAEnE,MAAM,WAAW,GAAG,KAAK,CAAC;AAE1B;;GAEG;AACH,MAAa,wBAAwB;IAQnC,YAAY,GAAQ;QAClB,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;IAClB,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,mHAAmH,CACpH,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,OAAO,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAErD,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;;gBAC/B,MAAM,KAAK,GACT,OAAO,IAAI,KAAK;oBACd,CAAC,CAAE,KAAK,CAAC,KAAe;oBACxB,CAAC,CAAC,IAAI,KAAK,CAAC,oBAAoB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC7D,MAAM,CAAC,KAAK,CAAC,CAAC;gBACd,MAAA,IAAI,CAAC,OAAO,qDAAG,KAAK,CAAC,CAAC;YACxB,CAAC,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE;gBACzB,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,GAAG,EAAE;;gBAC1B,MAAA,IAAI,CAAC,OAAO,oDAAI,CAAC;YACnB,CAAC,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,KAAmB,EAAE,EAAE;;gBAC/C,IAAI,OAAuB,CAAC;gBAC5B,IAAI,CAAC;oBACH,OAAO,GAAG,+BAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC/D,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAA,IAAI,CAAC,OAAO,qDAAG,KAAc,CAAC,CAAC;oBAC/B,OAAO;gBACT,CAAC;gBAED,MAAA,IAAI,CAAC,SAAS,qDAAG,OAAO,CAAC,CAAC;YAC5B,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK;;QACT,MAAA,IAAI,CAAC,OAAO,0CAAE,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,IAAI,CAAC,OAAuB;QAC1B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;;YACrC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClB,MAAM,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;gBACnC,OAAO;YACT,CAAC;YAED,MAAA,IAAI,CAAC,OAAO,0CAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;YAC5C,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AApED,4DAoEC"}
|
||||
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/multipleClientsParallel.d.ts
generated
vendored
Normal file
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/multipleClientsParallel.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=multipleClientsParallel.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/multipleClientsParallel.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/multipleClientsParallel.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"multipleClientsParallel.d.ts","sourceRoot":"","sources":["../../../../src/examples/client/multipleClientsParallel.ts"],"names":[],"mappings":""}
|
||||
134
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/multipleClientsParallel.js
generated
vendored
Normal file
134
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/multipleClientsParallel.js
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const index_js_1 = require("../../client/index.js");
|
||||
const streamableHttp_js_1 = require("../../client/streamableHttp.js");
|
||||
const types_js_1 = require("../../types.js");
|
||||
/**
|
||||
* Multiple Clients MCP Example
|
||||
*
|
||||
* This client demonstrates how to:
|
||||
* 1. Create multiple MCP clients in parallel
|
||||
* 2. Each client calls a single tool
|
||||
* 3. Track notifications from each client independently
|
||||
*/
|
||||
// Command line args processing
|
||||
const args = process.argv.slice(2);
|
||||
const serverUrl = args[0] || 'http://localhost:3000/mcp';
|
||||
async function createAndRunClient(config) {
|
||||
console.log(`[${config.id}] Creating client: ${config.name}`);
|
||||
const client = new index_js_1.Client({
|
||||
name: config.name,
|
||||
version: '1.0.0'
|
||||
});
|
||||
const transport = new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(serverUrl));
|
||||
// Set up client-specific error handler
|
||||
client.onerror = (error) => {
|
||||
console.error(`[${config.id}] Client error:`, error);
|
||||
};
|
||||
// Set up client-specific notification handler
|
||||
client.setNotificationHandler(types_js_1.LoggingMessageNotificationSchema, (notification) => {
|
||||
console.log(`[${config.id}] Notification: ${notification.params.data}`);
|
||||
});
|
||||
try {
|
||||
// Connect to the server
|
||||
await client.connect(transport);
|
||||
console.log(`[${config.id}] Connected to MCP server`);
|
||||
// Call the specified tool
|
||||
console.log(`[${config.id}] Calling tool: ${config.toolName}`);
|
||||
const toolRequest = {
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: config.toolName,
|
||||
arguments: {
|
||||
...config.toolArguments,
|
||||
// Add client ID to arguments for identification in notifications
|
||||
caller: config.id
|
||||
}
|
||||
}
|
||||
};
|
||||
const result = await client.request(toolRequest, types_js_1.CallToolResultSchema);
|
||||
console.log(`[${config.id}] Tool call completed`);
|
||||
// Keep the connection open for a bit to receive notifications
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
// Disconnect
|
||||
await transport.close();
|
||||
console.log(`[${config.id}] Disconnected from MCP server`);
|
||||
return { id: config.id, result };
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`[${config.id}] Error:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
async function main() {
|
||||
console.log('MCP Multiple Clients Example');
|
||||
console.log('============================');
|
||||
console.log(`Server URL: ${serverUrl}`);
|
||||
console.log('');
|
||||
try {
|
||||
// Define client configurations
|
||||
const clientConfigs = [
|
||||
{
|
||||
id: 'client1',
|
||||
name: 'basic-client-1',
|
||||
toolName: 'start-notification-stream',
|
||||
toolArguments: {
|
||||
interval: 3, // 1 second between notifications
|
||||
count: 5 // Send 5 notifications
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'client2',
|
||||
name: 'basic-client-2',
|
||||
toolName: 'start-notification-stream',
|
||||
toolArguments: {
|
||||
interval: 2, // 2 seconds between notifications
|
||||
count: 3 // Send 3 notifications
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'client3',
|
||||
name: 'basic-client-3',
|
||||
toolName: 'start-notification-stream',
|
||||
toolArguments: {
|
||||
interval: 1, // 0.5 second between notifications
|
||||
count: 8 // Send 8 notifications
|
||||
}
|
||||
}
|
||||
];
|
||||
// Start all clients in parallel
|
||||
console.log(`Starting ${clientConfigs.length} clients in parallel...`);
|
||||
console.log('');
|
||||
const clientPromises = clientConfigs.map(config => createAndRunClient(config));
|
||||
const results = await Promise.all(clientPromises);
|
||||
// Display results from all clients
|
||||
console.log('\n=== Final Results ===');
|
||||
results.forEach(({ id, result }) => {
|
||||
console.log(`\n[${id}] Tool result:`);
|
||||
if (Array.isArray(result.content)) {
|
||||
result.content.forEach((item) => {
|
||||
if (item.type === 'text' && item.text) {
|
||||
console.log(` ${item.text}`);
|
||||
}
|
||||
else {
|
||||
console.log(` ${item.type} content:`, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.log(` Unexpected result format:`, result);
|
||||
}
|
||||
});
|
||||
console.log('\n=== All clients completed successfully ===');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error running multiple clients:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
// Start the example
|
||||
main().catch((error) => {
|
||||
console.error('Error running MCP multiple clients example:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
//# sourceMappingURL=multipleClientsParallel.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/multipleClientsParallel.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/multipleClientsParallel.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"multipleClientsParallel.js","sourceRoot":"","sources":["../../../../src/examples/client/multipleClientsParallel.ts"],"names":[],"mappings":"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"}
|
||||
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/parallelToolCallsClient.d.ts
generated
vendored
Normal file
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/parallelToolCallsClient.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=parallelToolCallsClient.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/parallelToolCallsClient.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/parallelToolCallsClient.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"parallelToolCallsClient.d.ts","sourceRoot":"","sources":["../../../../src/examples/client/parallelToolCallsClient.ts"],"names":[],"mappings":""}
|
||||
175
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/parallelToolCallsClient.js
generated
vendored
Normal file
175
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/parallelToolCallsClient.js
generated
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const index_js_1 = require("../../client/index.js");
|
||||
const streamableHttp_js_1 = require("../../client/streamableHttp.js");
|
||||
const types_js_1 = require("../../types.js");
|
||||
/**
|
||||
* Parallel Tool Calls MCP Client
|
||||
*
|
||||
* This client demonstrates how to:
|
||||
* 1. Start multiple tool calls in parallel
|
||||
* 2. Track notifications from each tool call using a caller parameter
|
||||
*/
|
||||
// Command line args processing
|
||||
const args = process.argv.slice(2);
|
||||
const serverUrl = args[0] || 'http://localhost:3000/mcp';
|
||||
async function main() {
|
||||
console.log('MCP Parallel Tool Calls Client');
|
||||
console.log('==============================');
|
||||
console.log(`Connecting to server at: ${serverUrl}`);
|
||||
let client;
|
||||
let transport;
|
||||
try {
|
||||
// Create client with streamable HTTP transport
|
||||
client = new index_js_1.Client({
|
||||
name: 'parallel-tool-calls-client',
|
||||
version: '1.0.0'
|
||||
});
|
||||
client.onerror = (error) => {
|
||||
console.error('Client error:', error);
|
||||
};
|
||||
// Connect to the server
|
||||
transport = new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(serverUrl));
|
||||
await client.connect(transport);
|
||||
console.log('Successfully connected to MCP server');
|
||||
// Set up notification handler with caller identification
|
||||
client.setNotificationHandler(types_js_1.LoggingMessageNotificationSchema, (notification) => {
|
||||
console.log(`Notification: ${notification.params.data}`);
|
||||
});
|
||||
console.log("List tools");
|
||||
const toolsRequest = await listTools(client);
|
||||
console.log("Tools: ", toolsRequest);
|
||||
// 2. Start multiple notification tools in parallel
|
||||
console.log('\n=== Starting Multiple Notification Streams in Parallel ===');
|
||||
const toolResults = await startParallelNotificationTools(client);
|
||||
// Log the results from each tool call
|
||||
for (const [caller, result] of Object.entries(toolResults)) {
|
||||
console.log(`\n=== Tool result for ${caller} ===`);
|
||||
result.content.forEach((item) => {
|
||||
if (item.type === 'text') {
|
||||
console.log(` ${item.text}`);
|
||||
}
|
||||
else {
|
||||
console.log(` ${item.type} content:`, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
// 3. Wait for all notifications (10 seconds)
|
||||
console.log('\n=== Waiting for all notifications ===');
|
||||
await new Promise(resolve => setTimeout(resolve, 10000));
|
||||
// 4. Disconnect
|
||||
console.log('\n=== Disconnecting ===');
|
||||
await transport.close();
|
||||
console.log('Disconnected from MCP server');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error running client:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* List available tools on the server
|
||||
*/
|
||||
async function listTools(client) {
|
||||
try {
|
||||
const toolsRequest = {
|
||||
method: 'tools/list',
|
||||
params: {}
|
||||
};
|
||||
const toolsResult = await client.request(toolsRequest, types_js_1.ListToolsResultSchema);
|
||||
console.log('Available tools:');
|
||||
if (toolsResult.tools.length === 0) {
|
||||
console.log(' No tools available');
|
||||
}
|
||||
else {
|
||||
for (const tool of toolsResult.tools) {
|
||||
console.log(` - ${tool.name}: ${tool.description}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(`Tools not supported by this server: ${error}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Start multiple notification tools in parallel with different configurations
|
||||
* Each tool call includes a caller parameter to identify its notifications
|
||||
*/
|
||||
async function startParallelNotificationTools(client) {
|
||||
try {
|
||||
// Define multiple tool calls with different configurations
|
||||
const toolCalls = [
|
||||
{
|
||||
caller: 'fast-notifier',
|
||||
request: {
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'start-notification-stream',
|
||||
arguments: {
|
||||
interval: 2, // 0.5 second between notifications
|
||||
count: 10, // Send 10 notifications
|
||||
caller: 'fast-notifier' // Identify this tool call
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
caller: 'slow-notifier',
|
||||
request: {
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'start-notification-stream',
|
||||
arguments: {
|
||||
interval: 5, // 2 seconds between notifications
|
||||
count: 5, // Send 5 notifications
|
||||
caller: 'slow-notifier' // Identify this tool call
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
caller: 'burst-notifier',
|
||||
request: {
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'start-notification-stream',
|
||||
arguments: {
|
||||
interval: 1, // 0.1 second between notifications
|
||||
count: 3, // Send just 3 notifications
|
||||
caller: 'burst-notifier' // Identify this tool call
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
console.log(`Starting ${toolCalls.length} notification tools in parallel...`);
|
||||
// Start all tool calls in parallel
|
||||
const toolPromises = toolCalls.map(({ caller, request }) => {
|
||||
console.log(`Starting tool call for ${caller}...`);
|
||||
return client.request(request, types_js_1.CallToolResultSchema)
|
||||
.then(result => ({ caller, result }))
|
||||
.catch(error => {
|
||||
console.error(`Error in tool call for ${caller}:`, error);
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
// Wait for all tool calls to complete
|
||||
const results = await Promise.all(toolPromises);
|
||||
// Organize results by caller
|
||||
const resultsByTool = {};
|
||||
results.forEach(({ caller, result }) => {
|
||||
resultsByTool[caller] = result;
|
||||
});
|
||||
return resultsByTool;
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`Error starting parallel notification tools:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
// Start the client
|
||||
main().catch((error) => {
|
||||
console.error('Error running MCP client:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
//# sourceMappingURL=parallelToolCallsClient.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/parallelToolCallsClient.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/parallelToolCallsClient.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"parallelToolCallsClient.js","sourceRoot":"","sources":["../../../../src/examples/client/parallelToolCallsClient.ts"],"names":[],"mappings":"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"}
|
||||
3
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleOAuthClient.d.ts
generated
vendored
Normal file
3
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleOAuthClient.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
export {};
|
||||
//# sourceMappingURL=simpleOAuthClient.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleOAuthClient.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleOAuthClient.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"simpleOAuthClient.d.ts","sourceRoot":"","sources":["../../../../src/examples/client/simpleOAuthClient.ts"],"names":[],"mappings":""}
|
||||
372
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleOAuthClient.js
generated
vendored
Normal file
372
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleOAuthClient.js
generated
vendored
Normal file
@@ -0,0 +1,372 @@
|
||||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const node_http_1 = require("node:http");
|
||||
const node_readline_1 = require("node:readline");
|
||||
const node_url_1 = require("node:url");
|
||||
const node_child_process_1 = require("node:child_process");
|
||||
const index_js_1 = require("../../client/index.js");
|
||||
const streamableHttp_js_1 = require("../../client/streamableHttp.js");
|
||||
const types_js_1 = require("../../types.js");
|
||||
const auth_js_1 = require("../../client/auth.js");
|
||||
// Configuration
|
||||
const DEFAULT_SERVER_URL = 'http://localhost:3000/mcp';
|
||||
const CALLBACK_PORT = 8090; // Use different port than auth server (3001)
|
||||
const CALLBACK_URL = `http://localhost:${CALLBACK_PORT}/callback`;
|
||||
/**
|
||||
* In-memory OAuth client provider for demonstration purposes
|
||||
* In production, you should persist tokens securely
|
||||
*/
|
||||
class InMemoryOAuthClientProvider {
|
||||
constructor(_redirectUrl, _clientMetadata, onRedirect) {
|
||||
this._redirectUrl = _redirectUrl;
|
||||
this._clientMetadata = _clientMetadata;
|
||||
this._onRedirect = onRedirect || ((url) => {
|
||||
console.log(`Redirect to: ${url.toString()}`);
|
||||
});
|
||||
}
|
||||
get redirectUrl() {
|
||||
return this._redirectUrl;
|
||||
}
|
||||
get clientMetadata() {
|
||||
return this._clientMetadata;
|
||||
}
|
||||
clientInformation() {
|
||||
return this._clientInformation;
|
||||
}
|
||||
saveClientInformation(clientInformation) {
|
||||
this._clientInformation = clientInformation;
|
||||
}
|
||||
tokens() {
|
||||
return this._tokens;
|
||||
}
|
||||
saveTokens(tokens) {
|
||||
this._tokens = tokens;
|
||||
}
|
||||
redirectToAuthorization(authorizationUrl) {
|
||||
this._onRedirect(authorizationUrl);
|
||||
}
|
||||
saveCodeVerifier(codeVerifier) {
|
||||
this._codeVerifier = codeVerifier;
|
||||
}
|
||||
codeVerifier() {
|
||||
if (!this._codeVerifier) {
|
||||
throw new Error('No code verifier saved');
|
||||
}
|
||||
return this._codeVerifier;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Interactive MCP client with OAuth authentication
|
||||
* Demonstrates the complete OAuth flow with browser-based authorization
|
||||
*/
|
||||
class InteractiveOAuthClient {
|
||||
constructor(serverUrl) {
|
||||
this.serverUrl = serverUrl;
|
||||
this.client = null;
|
||||
this.rl = (0, node_readline_1.createInterface)({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Prompts user for input via readline
|
||||
*/
|
||||
async question(query) {
|
||||
return new Promise((resolve) => {
|
||||
this.rl.question(query, resolve);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Opens the authorization URL in the user's default browser
|
||||
*/
|
||||
async openBrowser(url) {
|
||||
console.log(`🌐 Opening browser for authorization: ${url}`);
|
||||
const command = `open "${url}"`;
|
||||
(0, node_child_process_1.exec)(command, (error) => {
|
||||
if (error) {
|
||||
console.error(`Failed to open browser: ${error.message}`);
|
||||
console.log(`Please manually open: ${url}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Example OAuth callback handler - in production, use a more robust approach
|
||||
* for handling callbacks and storing tokens
|
||||
*/
|
||||
/**
|
||||
* Starts a temporary HTTP server to receive the OAuth callback
|
||||
*/
|
||||
async waitForOAuthCallback() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const server = (0, node_http_1.createServer)((req, res) => {
|
||||
// Ignore favicon requests
|
||||
if (req.url === '/favicon.ico') {
|
||||
res.writeHead(404);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
console.log(`📥 Received callback: ${req.url}`);
|
||||
const parsedUrl = new node_url_1.URL(req.url || '', 'http://localhost');
|
||||
const code = parsedUrl.searchParams.get('code');
|
||||
const error = parsedUrl.searchParams.get('error');
|
||||
if (code) {
|
||||
console.log(`✅ Authorization code received: ${code === null || code === void 0 ? void 0 : code.substring(0, 10)}...`);
|
||||
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||
res.end(`
|
||||
<html>
|
||||
<body>
|
||||
<h1>Authorization Successful!</h1>
|
||||
<p>You can close this window and return to the terminal.</p>
|
||||
<script>setTimeout(() => window.close(), 2000);</script>
|
||||
</body>
|
||||
</html>
|
||||
`);
|
||||
resolve(code);
|
||||
setTimeout(() => server.close(), 3000);
|
||||
}
|
||||
else if (error) {
|
||||
console.log(`❌ Authorization error: ${error}`);
|
||||
res.writeHead(400, { 'Content-Type': 'text/html' });
|
||||
res.end(`
|
||||
<html>
|
||||
<body>
|
||||
<h1>Authorization Failed</h1>
|
||||
<p>Error: ${error}</p>
|
||||
</body>
|
||||
</html>
|
||||
`);
|
||||
reject(new Error(`OAuth authorization failed: ${error}`));
|
||||
}
|
||||
else {
|
||||
console.log(`❌ No authorization code or error in callback`);
|
||||
res.writeHead(400);
|
||||
res.end('Bad request');
|
||||
reject(new Error('No authorization code provided'));
|
||||
}
|
||||
});
|
||||
server.listen(CALLBACK_PORT, () => {
|
||||
console.log(`OAuth callback server started on http://localhost:${CALLBACK_PORT}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
async attemptConnection(oauthProvider) {
|
||||
console.log('🚢 Creating transport with OAuth provider...');
|
||||
const baseUrl = new node_url_1.URL(this.serverUrl);
|
||||
const transport = new streamableHttp_js_1.StreamableHTTPClientTransport(baseUrl, {
|
||||
authProvider: oauthProvider
|
||||
});
|
||||
console.log('🚢 Transport created');
|
||||
try {
|
||||
console.log('🔌 Attempting connection (this will trigger OAuth redirect)...');
|
||||
await this.client.connect(transport);
|
||||
console.log('✅ Connected successfully');
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof auth_js_1.UnauthorizedError) {
|
||||
console.log('🔐 OAuth required - waiting for authorization...');
|
||||
const callbackPromise = this.waitForOAuthCallback();
|
||||
const authCode = await callbackPromise;
|
||||
await transport.finishAuth(authCode);
|
||||
console.log('🔐 Authorization code received:', authCode);
|
||||
console.log('🔌 Reconnecting with authenticated transport...');
|
||||
await this.attemptConnection(oauthProvider);
|
||||
}
|
||||
else {
|
||||
console.error('❌ Connection failed with non-auth error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Establishes connection to the MCP server with OAuth authentication
|
||||
*/
|
||||
async connect() {
|
||||
console.log(`🔗 Attempting to connect to ${this.serverUrl}...`);
|
||||
const clientMetadata = {
|
||||
client_name: 'Simple OAuth MCP Client',
|
||||
redirect_uris: [CALLBACK_URL],
|
||||
grant_types: ['authorization_code', 'refresh_token'],
|
||||
response_types: ['code'],
|
||||
token_endpoint_auth_method: 'client_secret_post',
|
||||
scope: 'mcp:tools'
|
||||
};
|
||||
console.log('🔐 Creating OAuth provider...');
|
||||
const oauthProvider = new InMemoryOAuthClientProvider(CALLBACK_URL, clientMetadata, (redirectUrl) => {
|
||||
console.log(`📌 OAuth redirect handler called - opening browser`);
|
||||
console.log(`Opening browser to: ${redirectUrl.toString()}`);
|
||||
this.openBrowser(redirectUrl.toString());
|
||||
});
|
||||
console.log('🔐 OAuth provider created');
|
||||
console.log('👤 Creating MCP client...');
|
||||
this.client = new index_js_1.Client({
|
||||
name: 'simple-oauth-client',
|
||||
version: '1.0.0',
|
||||
}, { capabilities: {} });
|
||||
console.log('👤 Client created');
|
||||
console.log('🔐 Starting OAuth flow...');
|
||||
await this.attemptConnection(oauthProvider);
|
||||
// Start interactive loop
|
||||
await this.interactiveLoop();
|
||||
}
|
||||
/**
|
||||
* Main interactive loop for user commands
|
||||
*/
|
||||
async interactiveLoop() {
|
||||
console.log('\n🎯 Interactive MCP Client with OAuth');
|
||||
console.log('Commands:');
|
||||
console.log(' list - List available tools');
|
||||
console.log(' call <tool_name> [args] - Call a tool');
|
||||
console.log(' quit - Exit the client');
|
||||
console.log();
|
||||
while (true) {
|
||||
try {
|
||||
const command = await this.question('mcp> ');
|
||||
if (!command.trim()) {
|
||||
continue;
|
||||
}
|
||||
if (command === 'quit') {
|
||||
break;
|
||||
}
|
||||
else if (command === 'list') {
|
||||
await this.listTools();
|
||||
}
|
||||
else if (command.startsWith('call ')) {
|
||||
await this.handleCallTool(command);
|
||||
}
|
||||
else {
|
||||
console.log('❌ Unknown command. Try \'list\', \'call <tool_name>\', or \'quit\'');
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof Error && error.message === 'SIGINT') {
|
||||
console.log('\n\n👋 Goodbye!');
|
||||
break;
|
||||
}
|
||||
console.error('❌ Error:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
async listTools() {
|
||||
if (!this.client) {
|
||||
console.log('❌ Not connected to server');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const request = {
|
||||
method: 'tools/list',
|
||||
params: {},
|
||||
};
|
||||
const result = await this.client.request(request, types_js_1.ListToolsResultSchema);
|
||||
if (result.tools && result.tools.length > 0) {
|
||||
console.log('\n📋 Available tools:');
|
||||
result.tools.forEach((tool, index) => {
|
||||
console.log(`${index + 1}. ${tool.name}`);
|
||||
if (tool.description) {
|
||||
console.log(` Description: ${tool.description}`);
|
||||
}
|
||||
console.log();
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.log('No tools available');
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('❌ Failed to list tools:', error);
|
||||
}
|
||||
}
|
||||
async handleCallTool(command) {
|
||||
const parts = command.split(/\s+/);
|
||||
const toolName = parts[1];
|
||||
if (!toolName) {
|
||||
console.log('❌ Please specify a tool name');
|
||||
return;
|
||||
}
|
||||
// Parse arguments (simple JSON-like format)
|
||||
let toolArgs = {};
|
||||
if (parts.length > 2) {
|
||||
const argsString = parts.slice(2).join(' ');
|
||||
try {
|
||||
toolArgs = JSON.parse(argsString);
|
||||
}
|
||||
catch (_a) {
|
||||
console.log('❌ Invalid arguments format (expected JSON)');
|
||||
return;
|
||||
}
|
||||
}
|
||||
await this.callTool(toolName, toolArgs);
|
||||
}
|
||||
async callTool(toolName, toolArgs) {
|
||||
if (!this.client) {
|
||||
console.log('❌ Not connected to server');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const request = {
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: toolName,
|
||||
arguments: toolArgs,
|
||||
},
|
||||
};
|
||||
const result = await this.client.request(request, types_js_1.CallToolResultSchema);
|
||||
console.log(`\n🔧 Tool '${toolName}' result:`);
|
||||
if (result.content) {
|
||||
result.content.forEach((content) => {
|
||||
if (content.type === 'text') {
|
||||
console.log(content.text);
|
||||
}
|
||||
else {
|
||||
console.log(content);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.log(result);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`❌ Failed to call tool '${toolName}':`, error);
|
||||
}
|
||||
}
|
||||
close() {
|
||||
this.rl.close();
|
||||
if (this.client) {
|
||||
// Note: Client doesn't have a close method in the current implementation
|
||||
// This would typically close the transport connection
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Main entry point
|
||||
*/
|
||||
async function main() {
|
||||
const serverUrl = process.env.MCP_SERVER_URL || DEFAULT_SERVER_URL;
|
||||
console.log('🚀 Simple MCP OAuth Client');
|
||||
console.log(`Connecting to: ${serverUrl}`);
|
||||
console.log();
|
||||
const client = new InteractiveOAuthClient(serverUrl);
|
||||
// Handle graceful shutdown
|
||||
process.on('SIGINT', () => {
|
||||
console.log('\n\n👋 Goodbye!');
|
||||
client.close();
|
||||
process.exit(0);
|
||||
});
|
||||
try {
|
||||
await client.connect();
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to start client:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
// Run if this file is executed directly
|
||||
main().catch((error) => {
|
||||
console.error('Unhandled error:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
//# sourceMappingURL=simpleOAuthClient.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleOAuthClient.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleOAuthClient.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleStreamableHttp.d.ts
generated
vendored
Normal file
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleStreamableHttp.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=simpleStreamableHttp.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleStreamableHttp.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleStreamableHttp.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"simpleStreamableHttp.d.ts","sourceRoot":"","sources":["../../../../src/examples/client/simpleStreamableHttp.ts"],"names":[],"mappings":""}
|
||||
743
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleStreamableHttp.js
generated
vendored
Normal file
743
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleStreamableHttp.js
generated
vendored
Normal file
@@ -0,0 +1,743 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const index_js_1 = require("../../client/index.js");
|
||||
const streamableHttp_js_1 = require("../../client/streamableHttp.js");
|
||||
const node_readline_1 = require("node:readline");
|
||||
const types_js_1 = require("../../types.js");
|
||||
const metadataUtils_js_1 = require("../../shared/metadataUtils.js");
|
||||
const ajv_1 = __importDefault(require("ajv"));
|
||||
// Create readline interface for user input
|
||||
const readline = (0, node_readline_1.createInterface)({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
// Track received notifications for debugging resumability
|
||||
let notificationCount = 0;
|
||||
// Global client and transport for interactive commands
|
||||
let client = null;
|
||||
let transport = null;
|
||||
let serverUrl = 'http://localhost:3000/mcp';
|
||||
let notificationsToolLastEventId = undefined;
|
||||
let sessionId = undefined;
|
||||
async function main() {
|
||||
console.log('MCP Interactive Client');
|
||||
console.log('=====================');
|
||||
// Connect to server immediately with default settings
|
||||
await connect();
|
||||
// Print help and start the command loop
|
||||
printHelp();
|
||||
commandLoop();
|
||||
}
|
||||
function printHelp() {
|
||||
console.log('\nAvailable commands:');
|
||||
console.log(' connect [url] - Connect to MCP server (default: http://localhost:3000/mcp)');
|
||||
console.log(' disconnect - Disconnect from server');
|
||||
console.log(' terminate-session - Terminate the current session');
|
||||
console.log(' reconnect - Reconnect to the server');
|
||||
console.log(' list-tools - List available tools');
|
||||
console.log(' call-tool <name> [args] - Call a tool with optional JSON arguments');
|
||||
console.log(' greet [name] - Call the greet tool');
|
||||
console.log(' multi-greet [name] - Call the multi-greet tool with notifications');
|
||||
console.log(' collect-info [type] - Test elicitation with collect-user-info tool (contact/preferences/feedback)');
|
||||
console.log(' start-notifications [interval] [count] - Start periodic notifications');
|
||||
console.log(' run-notifications-tool-with-resumability [interval] [count] - Run notification tool with resumability');
|
||||
console.log(' list-prompts - List available prompts');
|
||||
console.log(' get-prompt [name] [args] - Get a prompt with optional JSON arguments');
|
||||
console.log(' list-resources - List available resources');
|
||||
console.log(' read-resource <uri> - Read a specific resource by URI');
|
||||
console.log(' help - Show this help');
|
||||
console.log(' quit - Exit the program');
|
||||
}
|
||||
function commandLoop() {
|
||||
readline.question('\n> ', async (input) => {
|
||||
var _a;
|
||||
const args = input.trim().split(/\s+/);
|
||||
const command = (_a = args[0]) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
||||
try {
|
||||
switch (command) {
|
||||
case 'connect':
|
||||
await connect(args[1]);
|
||||
break;
|
||||
case 'disconnect':
|
||||
await disconnect();
|
||||
break;
|
||||
case 'terminate-session':
|
||||
await terminateSession();
|
||||
break;
|
||||
case 'reconnect':
|
||||
await reconnect();
|
||||
break;
|
||||
case 'list-tools':
|
||||
await listTools();
|
||||
break;
|
||||
case 'call-tool':
|
||||
if (args.length < 2) {
|
||||
console.log('Usage: call-tool <name> [args]');
|
||||
}
|
||||
else {
|
||||
const toolName = args[1];
|
||||
let toolArgs = {};
|
||||
if (args.length > 2) {
|
||||
try {
|
||||
toolArgs = JSON.parse(args.slice(2).join(' '));
|
||||
}
|
||||
catch (_b) {
|
||||
console.log('Invalid JSON arguments. Using empty args.');
|
||||
}
|
||||
}
|
||||
await callTool(toolName, toolArgs);
|
||||
}
|
||||
break;
|
||||
case 'greet':
|
||||
await callGreetTool(args[1] || 'MCP User');
|
||||
break;
|
||||
case 'multi-greet':
|
||||
await callMultiGreetTool(args[1] || 'MCP User');
|
||||
break;
|
||||
case 'collect-info':
|
||||
await callCollectInfoTool(args[1] || 'contact');
|
||||
break;
|
||||
case 'start-notifications': {
|
||||
const interval = args[1] ? parseInt(args[1], 10) : 2000;
|
||||
const count = args[2] ? parseInt(args[2], 10) : 10;
|
||||
await startNotifications(interval, count);
|
||||
break;
|
||||
}
|
||||
case 'run-notifications-tool-with-resumability': {
|
||||
const interval = args[1] ? parseInt(args[1], 10) : 2000;
|
||||
const count = args[2] ? parseInt(args[2], 10) : 10;
|
||||
await runNotificationsToolWithResumability(interval, count);
|
||||
break;
|
||||
}
|
||||
case 'list-prompts':
|
||||
await listPrompts();
|
||||
break;
|
||||
case 'get-prompt':
|
||||
if (args.length < 2) {
|
||||
console.log('Usage: get-prompt <name> [args]');
|
||||
}
|
||||
else {
|
||||
const promptName = args[1];
|
||||
let promptArgs = {};
|
||||
if (args.length > 2) {
|
||||
try {
|
||||
promptArgs = JSON.parse(args.slice(2).join(' '));
|
||||
}
|
||||
catch (_c) {
|
||||
console.log('Invalid JSON arguments. Using empty args.');
|
||||
}
|
||||
}
|
||||
await getPrompt(promptName, promptArgs);
|
||||
}
|
||||
break;
|
||||
case 'list-resources':
|
||||
await listResources();
|
||||
break;
|
||||
case 'read-resource':
|
||||
if (args.length < 2) {
|
||||
console.log('Usage: read-resource <uri>');
|
||||
}
|
||||
else {
|
||||
await readResource(args[1]);
|
||||
}
|
||||
break;
|
||||
case 'help':
|
||||
printHelp();
|
||||
break;
|
||||
case 'quit':
|
||||
case 'exit':
|
||||
await cleanup();
|
||||
return;
|
||||
default:
|
||||
if (command) {
|
||||
console.log(`Unknown command: ${command}`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`Error executing command: ${error}`);
|
||||
}
|
||||
// Continue the command loop
|
||||
commandLoop();
|
||||
});
|
||||
}
|
||||
async function connect(url) {
|
||||
if (client) {
|
||||
console.log('Already connected. Disconnect first.');
|
||||
return;
|
||||
}
|
||||
if (url) {
|
||||
serverUrl = url;
|
||||
}
|
||||
console.log(`Connecting to ${serverUrl}...`);
|
||||
try {
|
||||
// Create a new client with elicitation capability
|
||||
client = new index_js_1.Client({
|
||||
name: 'example-client',
|
||||
version: '1.0.0'
|
||||
}, {
|
||||
capabilities: {
|
||||
elicitation: {},
|
||||
},
|
||||
});
|
||||
client.onerror = (error) => {
|
||||
console.error('\x1b[31mClient error:', error, '\x1b[0m');
|
||||
};
|
||||
// Set up elicitation request handler with proper validation
|
||||
client.setRequestHandler(types_js_1.ElicitRequestSchema, async (request) => {
|
||||
var _a;
|
||||
console.log('\n🔔 Elicitation Request Received:');
|
||||
console.log(`Message: ${request.params.message}`);
|
||||
console.log('Requested Schema:');
|
||||
console.log(JSON.stringify(request.params.requestedSchema, null, 2));
|
||||
const schema = request.params.requestedSchema;
|
||||
const properties = schema.properties;
|
||||
const required = schema.required || [];
|
||||
// Set up AJV validator for the requested schema
|
||||
const ajv = new ajv_1.default();
|
||||
const validate = ajv.compile(schema);
|
||||
let attempts = 0;
|
||||
const maxAttempts = 3;
|
||||
while (attempts < maxAttempts) {
|
||||
attempts++;
|
||||
console.log(`\nPlease provide the following information (attempt ${attempts}/${maxAttempts}):`);
|
||||
const content = {};
|
||||
let inputCancelled = false;
|
||||
// Collect input for each field
|
||||
for (const [fieldName, fieldSchema] of Object.entries(properties)) {
|
||||
const field = fieldSchema;
|
||||
const isRequired = required.includes(fieldName);
|
||||
let prompt = `${field.title || fieldName}`;
|
||||
// Add helpful information to the prompt
|
||||
if (field.description) {
|
||||
prompt += ` (${field.description})`;
|
||||
}
|
||||
if (field.enum) {
|
||||
prompt += ` [options: ${field.enum.join(', ')}]`;
|
||||
}
|
||||
if (field.type === 'number' || field.type === 'integer') {
|
||||
if (field.minimum !== undefined && field.maximum !== undefined) {
|
||||
prompt += ` [${field.minimum}-${field.maximum}]`;
|
||||
}
|
||||
else if (field.minimum !== undefined) {
|
||||
prompt += ` [min: ${field.minimum}]`;
|
||||
}
|
||||
else if (field.maximum !== undefined) {
|
||||
prompt += ` [max: ${field.maximum}]`;
|
||||
}
|
||||
}
|
||||
if (field.type === 'string' && field.format) {
|
||||
prompt += ` [format: ${field.format}]`;
|
||||
}
|
||||
if (isRequired) {
|
||||
prompt += ' *required*';
|
||||
}
|
||||
if (field.default !== undefined) {
|
||||
prompt += ` [default: ${field.default}]`;
|
||||
}
|
||||
prompt += ': ';
|
||||
const answer = await new Promise((resolve) => {
|
||||
readline.question(prompt, (input) => {
|
||||
resolve(input.trim());
|
||||
});
|
||||
});
|
||||
// Check for cancellation
|
||||
if (answer.toLowerCase() === 'cancel' || answer.toLowerCase() === 'c') {
|
||||
inputCancelled = true;
|
||||
break;
|
||||
}
|
||||
// Parse and validate the input
|
||||
try {
|
||||
if (answer === '' && field.default !== undefined) {
|
||||
content[fieldName] = field.default;
|
||||
}
|
||||
else if (answer === '' && !isRequired) {
|
||||
// Skip optional empty fields
|
||||
continue;
|
||||
}
|
||||
else if (answer === '') {
|
||||
throw new Error(`${fieldName} is required`);
|
||||
}
|
||||
else {
|
||||
// Parse the value based on type
|
||||
let parsedValue;
|
||||
if (field.type === 'boolean') {
|
||||
parsedValue = answer.toLowerCase() === 'true' || answer.toLowerCase() === 'yes' || answer === '1';
|
||||
}
|
||||
else if (field.type === 'number') {
|
||||
parsedValue = parseFloat(answer);
|
||||
if (isNaN(parsedValue)) {
|
||||
throw new Error(`${fieldName} must be a valid number`);
|
||||
}
|
||||
}
|
||||
else if (field.type === 'integer') {
|
||||
parsedValue = parseInt(answer, 10);
|
||||
if (isNaN(parsedValue)) {
|
||||
throw new Error(`${fieldName} must be a valid integer`);
|
||||
}
|
||||
}
|
||||
else if (field.enum) {
|
||||
if (!field.enum.includes(answer)) {
|
||||
throw new Error(`${fieldName} must be one of: ${field.enum.join(', ')}`);
|
||||
}
|
||||
parsedValue = answer;
|
||||
}
|
||||
else {
|
||||
parsedValue = answer;
|
||||
}
|
||||
content[fieldName] = parsedValue;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(`❌ Error: ${error}`);
|
||||
// Continue to next attempt
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (inputCancelled) {
|
||||
return { action: 'cancel' };
|
||||
}
|
||||
// If we didn't complete all fields due to an error, try again
|
||||
if (Object.keys(content).length !== Object.keys(properties).filter(name => required.includes(name) || content[name] !== undefined).length) {
|
||||
if (attempts < maxAttempts) {
|
||||
console.log('Please try again...');
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
console.log('Maximum attempts reached. Declining request.');
|
||||
return { action: 'decline' };
|
||||
}
|
||||
}
|
||||
// Validate the complete object against the schema
|
||||
const isValid = validate(content);
|
||||
if (!isValid) {
|
||||
console.log('❌ Validation errors:');
|
||||
(_a = validate.errors) === null || _a === void 0 ? void 0 : _a.forEach(error => {
|
||||
console.log(` - ${error.dataPath || 'root'}: ${error.message}`);
|
||||
});
|
||||
if (attempts < maxAttempts) {
|
||||
console.log('Please correct the errors and try again...');
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
console.log('Maximum attempts reached. Declining request.');
|
||||
return { action: 'decline' };
|
||||
}
|
||||
}
|
||||
// Show the collected data and ask for confirmation
|
||||
console.log('\n✅ Collected data:');
|
||||
console.log(JSON.stringify(content, null, 2));
|
||||
const confirmAnswer = await new Promise((resolve) => {
|
||||
readline.question('\nSubmit this information? (yes/no/cancel): ', (input) => {
|
||||
resolve(input.trim().toLowerCase());
|
||||
});
|
||||
});
|
||||
if (confirmAnswer === 'yes' || confirmAnswer === 'y') {
|
||||
return {
|
||||
action: 'accept',
|
||||
content,
|
||||
};
|
||||
}
|
||||
else if (confirmAnswer === 'cancel' || confirmAnswer === 'c') {
|
||||
return { action: 'cancel' };
|
||||
}
|
||||
else if (confirmAnswer === 'no' || confirmAnswer === 'n') {
|
||||
if (attempts < maxAttempts) {
|
||||
console.log('Please re-enter the information...');
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
return { action: 'decline' };
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log('Maximum attempts reached. Declining request.');
|
||||
return { action: 'decline' };
|
||||
});
|
||||
transport = new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(serverUrl), {
|
||||
sessionId: sessionId
|
||||
});
|
||||
// Set up notification handlers
|
||||
client.setNotificationHandler(types_js_1.LoggingMessageNotificationSchema, (notification) => {
|
||||
notificationCount++;
|
||||
console.log(`\nNotification #${notificationCount}: ${notification.params.level} - ${notification.params.data}`);
|
||||
// Re-display the prompt
|
||||
process.stdout.write('> ');
|
||||
});
|
||||
client.setNotificationHandler(types_js_1.ResourceListChangedNotificationSchema, async (_) => {
|
||||
console.log(`\nResource list changed notification received!`);
|
||||
try {
|
||||
if (!client) {
|
||||
console.log('Client disconnected, cannot fetch resources');
|
||||
return;
|
||||
}
|
||||
const resourcesResult = await client.request({
|
||||
method: 'resources/list',
|
||||
params: {}
|
||||
}, types_js_1.ListResourcesResultSchema);
|
||||
console.log('Available resources count:', resourcesResult.resources.length);
|
||||
}
|
||||
catch (_a) {
|
||||
console.log('Failed to list resources after change notification');
|
||||
}
|
||||
// Re-display the prompt
|
||||
process.stdout.write('> ');
|
||||
});
|
||||
// Connect the client
|
||||
await client.connect(transport);
|
||||
sessionId = transport.sessionId;
|
||||
console.log('Transport created with session ID:', sessionId);
|
||||
console.log('Connected to MCP server');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to connect:', error);
|
||||
client = null;
|
||||
transport = null;
|
||||
}
|
||||
}
|
||||
async function disconnect() {
|
||||
if (!client || !transport) {
|
||||
console.log('Not connected.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await transport.close();
|
||||
console.log('Disconnected from MCP server');
|
||||
client = null;
|
||||
transport = null;
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error disconnecting:', error);
|
||||
}
|
||||
}
|
||||
async function terminateSession() {
|
||||
if (!client || !transport) {
|
||||
console.log('Not connected.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
console.log('Terminating session with ID:', transport.sessionId);
|
||||
await transport.terminateSession();
|
||||
console.log('Session terminated successfully');
|
||||
// Check if sessionId was cleared after termination
|
||||
if (!transport.sessionId) {
|
||||
console.log('Session ID has been cleared');
|
||||
sessionId = undefined;
|
||||
// Also close the transport and clear client objects
|
||||
await transport.close();
|
||||
console.log('Transport closed after session termination');
|
||||
client = null;
|
||||
transport = null;
|
||||
}
|
||||
else {
|
||||
console.log('Server responded with 405 Method Not Allowed (session termination not supported)');
|
||||
console.log('Session ID is still active:', transport.sessionId);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error terminating session:', error);
|
||||
}
|
||||
}
|
||||
async function reconnect() {
|
||||
if (client) {
|
||||
await disconnect();
|
||||
}
|
||||
await connect();
|
||||
}
|
||||
async function listTools() {
|
||||
if (!client) {
|
||||
console.log('Not connected to server.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const toolsRequest = {
|
||||
method: 'tools/list',
|
||||
params: {}
|
||||
};
|
||||
const toolsResult = await client.request(toolsRequest, types_js_1.ListToolsResultSchema);
|
||||
console.log('Available tools:');
|
||||
if (toolsResult.tools.length === 0) {
|
||||
console.log(' No tools available');
|
||||
}
|
||||
else {
|
||||
for (const tool of toolsResult.tools) {
|
||||
console.log(` - id: ${tool.name}, name: ${(0, metadataUtils_js_1.getDisplayName)(tool)}, description: ${tool.description}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(`Tools not supported by this server (${error})`);
|
||||
}
|
||||
}
|
||||
async function callTool(name, args) {
|
||||
if (!client) {
|
||||
console.log('Not connected to server.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const request = {
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name,
|
||||
arguments: args
|
||||
}
|
||||
};
|
||||
console.log(`Calling tool '${name}' with args:`, args);
|
||||
const result = await client.request(request, types_js_1.CallToolResultSchema);
|
||||
console.log('Tool result:');
|
||||
const resourceLinks = [];
|
||||
result.content.forEach(item => {
|
||||
if (item.type === 'text') {
|
||||
console.log(` ${item.text}`);
|
||||
}
|
||||
else if (item.type === 'resource_link') {
|
||||
const resourceLink = item;
|
||||
resourceLinks.push(resourceLink);
|
||||
console.log(` 📁 Resource Link: ${resourceLink.name}`);
|
||||
console.log(` URI: ${resourceLink.uri}`);
|
||||
if (resourceLink.mimeType) {
|
||||
console.log(` Type: ${resourceLink.mimeType}`);
|
||||
}
|
||||
if (resourceLink.description) {
|
||||
console.log(` Description: ${resourceLink.description}`);
|
||||
}
|
||||
}
|
||||
else if (item.type === 'resource') {
|
||||
console.log(` [Embedded Resource: ${item.resource.uri}]`);
|
||||
}
|
||||
else if (item.type === 'image') {
|
||||
console.log(` [Image: ${item.mimeType}]`);
|
||||
}
|
||||
else if (item.type === 'audio') {
|
||||
console.log(` [Audio: ${item.mimeType}]`);
|
||||
}
|
||||
else {
|
||||
console.log(` [Unknown content type]:`, item);
|
||||
}
|
||||
});
|
||||
// Offer to read resource links
|
||||
if (resourceLinks.length > 0) {
|
||||
console.log(`\nFound ${resourceLinks.length} resource link(s). Use 'read-resource <uri>' to read their content.`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(`Error calling tool ${name}: ${error}`);
|
||||
}
|
||||
}
|
||||
async function callGreetTool(name) {
|
||||
await callTool('greet', { name });
|
||||
}
|
||||
async function callMultiGreetTool(name) {
|
||||
console.log('Calling multi-greet tool with notifications...');
|
||||
await callTool('multi-greet', { name });
|
||||
}
|
||||
async function callCollectInfoTool(infoType) {
|
||||
console.log(`Testing elicitation with collect-user-info tool (${infoType})...`);
|
||||
await callTool('collect-user-info', { infoType });
|
||||
}
|
||||
async function startNotifications(interval, count) {
|
||||
console.log(`Starting notification stream: interval=${interval}ms, count=${count || 'unlimited'}`);
|
||||
await callTool('start-notification-stream', { interval, count });
|
||||
}
|
||||
async function runNotificationsToolWithResumability(interval, count) {
|
||||
if (!client) {
|
||||
console.log('Not connected to server.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
console.log(`Starting notification stream with resumability: interval=${interval}ms, count=${count || 'unlimited'}`);
|
||||
console.log(`Using resumption token: ${notificationsToolLastEventId || 'none'}`);
|
||||
const request = {
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'start-notification-stream',
|
||||
arguments: { interval, count }
|
||||
}
|
||||
};
|
||||
const onLastEventIdUpdate = (event) => {
|
||||
notificationsToolLastEventId = event;
|
||||
console.log(`Updated resumption token: ${event}`);
|
||||
};
|
||||
const result = await client.request(request, types_js_1.CallToolResultSchema, {
|
||||
resumptionToken: notificationsToolLastEventId,
|
||||
onresumptiontoken: onLastEventIdUpdate
|
||||
});
|
||||
console.log('Tool result:');
|
||||
result.content.forEach(item => {
|
||||
if (item.type === 'text') {
|
||||
console.log(` ${item.text}`);
|
||||
}
|
||||
else {
|
||||
console.log(` ${item.type} content:`, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
console.log(`Error starting notification stream: ${error}`);
|
||||
}
|
||||
}
|
||||
async function listPrompts() {
|
||||
if (!client) {
|
||||
console.log('Not connected to server.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const promptsRequest = {
|
||||
method: 'prompts/list',
|
||||
params: {}
|
||||
};
|
||||
const promptsResult = await client.request(promptsRequest, types_js_1.ListPromptsResultSchema);
|
||||
console.log('Available prompts:');
|
||||
if (promptsResult.prompts.length === 0) {
|
||||
console.log(' No prompts available');
|
||||
}
|
||||
else {
|
||||
for (const prompt of promptsResult.prompts) {
|
||||
console.log(` - id: ${prompt.name}, name: ${(0, metadataUtils_js_1.getDisplayName)(prompt)}, description: ${prompt.description}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(`Prompts not supported by this server (${error})`);
|
||||
}
|
||||
}
|
||||
async function getPrompt(name, args) {
|
||||
if (!client) {
|
||||
console.log('Not connected to server.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const promptRequest = {
|
||||
method: 'prompts/get',
|
||||
params: {
|
||||
name,
|
||||
arguments: args
|
||||
}
|
||||
};
|
||||
const promptResult = await client.request(promptRequest, types_js_1.GetPromptResultSchema);
|
||||
console.log('Prompt template:');
|
||||
promptResult.messages.forEach((msg, index) => {
|
||||
console.log(` [${index + 1}] ${msg.role}: ${msg.content.text}`);
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
console.log(`Error getting prompt ${name}: ${error}`);
|
||||
}
|
||||
}
|
||||
async function listResources() {
|
||||
if (!client) {
|
||||
console.log('Not connected to server.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const resourcesRequest = {
|
||||
method: 'resources/list',
|
||||
params: {}
|
||||
};
|
||||
const resourcesResult = await client.request(resourcesRequest, types_js_1.ListResourcesResultSchema);
|
||||
console.log('Available resources:');
|
||||
if (resourcesResult.resources.length === 0) {
|
||||
console.log(' No resources available');
|
||||
}
|
||||
else {
|
||||
for (const resource of resourcesResult.resources) {
|
||||
console.log(` - id: ${resource.name}, name: ${(0, metadataUtils_js_1.getDisplayName)(resource)}, description: ${resource.uri}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(`Resources not supported by this server (${error})`);
|
||||
}
|
||||
}
|
||||
async function readResource(uri) {
|
||||
if (!client) {
|
||||
console.log('Not connected to server.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const request = {
|
||||
method: 'resources/read',
|
||||
params: { uri }
|
||||
};
|
||||
console.log(`Reading resource: ${uri}`);
|
||||
const result = await client.request(request, types_js_1.ReadResourceResultSchema);
|
||||
console.log('Resource contents:');
|
||||
for (const content of result.contents) {
|
||||
console.log(` URI: ${content.uri}`);
|
||||
if (content.mimeType) {
|
||||
console.log(` Type: ${content.mimeType}`);
|
||||
}
|
||||
if ('text' in content && typeof content.text === 'string') {
|
||||
console.log(' Content:');
|
||||
console.log(' ---');
|
||||
console.log(content.text.split('\n').map((line) => ' ' + line).join('\n'));
|
||||
console.log(' ---');
|
||||
}
|
||||
else if ('blob' in content && typeof content.blob === 'string') {
|
||||
console.log(` [Binary data: ${content.blob.length} bytes]`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(`Error reading resource ${uri}: ${error}`);
|
||||
}
|
||||
}
|
||||
async function cleanup() {
|
||||
if (client && transport) {
|
||||
try {
|
||||
// First try to terminate the session gracefully
|
||||
if (transport.sessionId) {
|
||||
try {
|
||||
console.log('Terminating session before exit...');
|
||||
await transport.terminateSession();
|
||||
console.log('Session terminated successfully');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error terminating session:', error);
|
||||
}
|
||||
}
|
||||
// Then close the transport
|
||||
await transport.close();
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error closing transport:', error);
|
||||
}
|
||||
}
|
||||
process.stdin.setRawMode(false);
|
||||
readline.close();
|
||||
console.log('\nGoodbye!');
|
||||
process.exit(0);
|
||||
}
|
||||
// Set up raw mode for keyboard input to capture Escape key
|
||||
process.stdin.setRawMode(true);
|
||||
process.stdin.on('data', async (data) => {
|
||||
// Check for Escape key (27)
|
||||
if (data.length === 1 && data[0] === 27) {
|
||||
console.log('\nESC key pressed. Disconnecting from server...');
|
||||
// Abort current operation and disconnect from server
|
||||
if (client && transport) {
|
||||
await disconnect();
|
||||
console.log('Disconnected. Press Enter to continue.');
|
||||
}
|
||||
else {
|
||||
console.log('Not connected to server.');
|
||||
}
|
||||
// Re-display the prompt
|
||||
process.stdout.write('> ');
|
||||
}
|
||||
});
|
||||
// Handle Ctrl+C
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('\nReceived SIGINT. Cleaning up...');
|
||||
await cleanup();
|
||||
});
|
||||
// Start the interactive client
|
||||
main().catch((error) => {
|
||||
console.error('Error running MCP client:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
//# sourceMappingURL=simpleStreamableHttp.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleStreamableHttp.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleStreamableHttp.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/streamableHttpWithSseFallbackClient.d.ts
generated
vendored
Normal file
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/streamableHttpWithSseFallbackClient.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=streamableHttpWithSseFallbackClient.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/streamableHttpWithSseFallbackClient.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/streamableHttpWithSseFallbackClient.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"streamableHttpWithSseFallbackClient.d.ts","sourceRoot":"","sources":["../../../../src/examples/client/streamableHttpWithSseFallbackClient.ts"],"names":[],"mappings":""}
|
||||
168
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/streamableHttpWithSseFallbackClient.js
generated
vendored
Normal file
168
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/streamableHttpWithSseFallbackClient.js
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const index_js_1 = require("../../client/index.js");
|
||||
const streamableHttp_js_1 = require("../../client/streamableHttp.js");
|
||||
const sse_js_1 = require("../../client/sse.js");
|
||||
const types_js_1 = require("../../types.js");
|
||||
/**
|
||||
* Simplified Backwards Compatible MCP Client
|
||||
*
|
||||
* This client demonstrates backward compatibility with both:
|
||||
* 1. Modern servers using Streamable HTTP transport (protocol version 2025-03-26)
|
||||
* 2. Older servers using HTTP+SSE transport (protocol version 2024-11-05)
|
||||
*
|
||||
* Following the MCP specification for backwards compatibility:
|
||||
* - Attempts to POST an initialize request to the server URL first (modern transport)
|
||||
* - If that fails with 4xx status, falls back to GET request for SSE stream (older transport)
|
||||
*/
|
||||
// Command line args processing
|
||||
const args = process.argv.slice(2);
|
||||
const serverUrl = args[0] || 'http://localhost:3000/mcp';
|
||||
async function main() {
|
||||
console.log('MCP Backwards Compatible Client');
|
||||
console.log('===============================');
|
||||
console.log(`Connecting to server at: ${serverUrl}`);
|
||||
let client;
|
||||
let transport;
|
||||
try {
|
||||
// Try connecting with automatic transport detection
|
||||
const connection = await connectWithBackwardsCompatibility(serverUrl);
|
||||
client = connection.client;
|
||||
transport = connection.transport;
|
||||
// Set up notification handler
|
||||
client.setNotificationHandler(types_js_1.LoggingMessageNotificationSchema, (notification) => {
|
||||
console.log(`Notification: ${notification.params.level} - ${notification.params.data}`);
|
||||
});
|
||||
// DEMO WORKFLOW:
|
||||
// 1. List available tools
|
||||
console.log('\n=== Listing Available Tools ===');
|
||||
await listTools(client);
|
||||
// 2. Call the notification tool
|
||||
console.log('\n=== Starting Notification Stream ===');
|
||||
await startNotificationTool(client);
|
||||
// 3. Wait for all notifications (5 seconds)
|
||||
console.log('\n=== Waiting for all notifications ===');
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
// 4. Disconnect
|
||||
console.log('\n=== Disconnecting ===');
|
||||
await transport.close();
|
||||
console.log('Disconnected from MCP server');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error running client:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Connect to an MCP server with backwards compatibility
|
||||
* Following the spec for client backward compatibility
|
||||
*/
|
||||
async function connectWithBackwardsCompatibility(url) {
|
||||
console.log('1. Trying Streamable HTTP transport first...');
|
||||
// Step 1: Try Streamable HTTP transport first
|
||||
const client = new index_js_1.Client({
|
||||
name: 'backwards-compatible-client',
|
||||
version: '1.0.0'
|
||||
});
|
||||
client.onerror = (error) => {
|
||||
console.error('Client error:', error);
|
||||
};
|
||||
const baseUrl = new URL(url);
|
||||
try {
|
||||
// Create modern transport
|
||||
const streamableTransport = new streamableHttp_js_1.StreamableHTTPClientTransport(baseUrl);
|
||||
await client.connect(streamableTransport);
|
||||
console.log('Successfully connected using modern Streamable HTTP transport.');
|
||||
return {
|
||||
client,
|
||||
transport: streamableTransport,
|
||||
transportType: 'streamable-http'
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
// Step 2: If transport fails, try the older SSE transport
|
||||
console.log(`StreamableHttp transport connection failed: ${error}`);
|
||||
console.log('2. Falling back to deprecated HTTP+SSE transport...');
|
||||
try {
|
||||
// Create SSE transport pointing to /sse endpoint
|
||||
const sseTransport = new sse_js_1.SSEClientTransport(baseUrl);
|
||||
const sseClient = new index_js_1.Client({
|
||||
name: 'backwards-compatible-client',
|
||||
version: '1.0.0'
|
||||
});
|
||||
await sseClient.connect(sseTransport);
|
||||
console.log('Successfully connected using deprecated HTTP+SSE transport.');
|
||||
return {
|
||||
client: sseClient,
|
||||
transport: sseTransport,
|
||||
transportType: 'sse'
|
||||
};
|
||||
}
|
||||
catch (sseError) {
|
||||
console.error(`Failed to connect with either transport method:\n1. Streamable HTTP error: ${error}\n2. SSE error: ${sseError}`);
|
||||
throw new Error('Could not connect to server with any available transport');
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* List available tools on the server
|
||||
*/
|
||||
async function listTools(client) {
|
||||
try {
|
||||
const toolsRequest = {
|
||||
method: 'tools/list',
|
||||
params: {}
|
||||
};
|
||||
const toolsResult = await client.request(toolsRequest, types_js_1.ListToolsResultSchema);
|
||||
console.log('Available tools:');
|
||||
if (toolsResult.tools.length === 0) {
|
||||
console.log(' No tools available');
|
||||
}
|
||||
else {
|
||||
for (const tool of toolsResult.tools) {
|
||||
console.log(` - ${tool.name}: ${tool.description}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(`Tools not supported by this server: ${error}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Start a notification stream by calling the notification tool
|
||||
*/
|
||||
async function startNotificationTool(client) {
|
||||
try {
|
||||
// Call the notification tool using reasonable defaults
|
||||
const request = {
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'start-notification-stream',
|
||||
arguments: {
|
||||
interval: 1000, // 1 second between notifications
|
||||
count: 5 // Send 5 notifications
|
||||
}
|
||||
}
|
||||
};
|
||||
console.log('Calling notification tool...');
|
||||
const result = await client.request(request, types_js_1.CallToolResultSchema);
|
||||
console.log('Tool result:');
|
||||
result.content.forEach(item => {
|
||||
if (item.type === 'text') {
|
||||
console.log(` ${item.text}`);
|
||||
}
|
||||
else {
|
||||
console.log(` ${item.type} content:`, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
console.log(`Error calling notification tool: ${error}`);
|
||||
}
|
||||
}
|
||||
// Start the client
|
||||
main().catch((error) => {
|
||||
console.error('Error running MCP client:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
//# sourceMappingURL=streamableHttpWithSseFallbackClient.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/streamableHttpWithSseFallbackClient.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/streamableHttpWithSseFallbackClient.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"streamableHttpWithSseFallbackClient.js","sourceRoot":"","sources":["../../../../src/examples/client/streamableHttpWithSseFallbackClient.ts"],"names":[],"mappings":"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"}
|
||||
78
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/demoInMemoryOAuthProvider.d.ts
generated
vendored
Normal file
78
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/demoInMemoryOAuthProvider.d.ts
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
import { AuthorizationParams, OAuthServerProvider } from '../../server/auth/provider.js';
|
||||
import { OAuthRegisteredClientsStore } from '../../server/auth/clients.js';
|
||||
import { OAuthClientInformationFull, OAuthMetadata, OAuthTokens } from '../../shared/auth.js';
|
||||
import { Response } from "express";
|
||||
import { AuthInfo } from '../../server/auth/types.js';
|
||||
export declare class DemoInMemoryClientsStore implements OAuthRegisteredClientsStore {
|
||||
private clients;
|
||||
getClient(clientId: string): Promise<{
|
||||
redirect_uris: string[];
|
||||
client_id: string;
|
||||
jwks_uri?: string | undefined;
|
||||
scope?: string | undefined;
|
||||
token_endpoint_auth_method?: string | undefined;
|
||||
grant_types?: string[] | undefined;
|
||||
response_types?: string[] | undefined;
|
||||
client_name?: string | undefined;
|
||||
client_uri?: string | undefined;
|
||||
logo_uri?: string | undefined;
|
||||
contacts?: string[] | undefined;
|
||||
tos_uri?: string | undefined;
|
||||
policy_uri?: string | undefined;
|
||||
jwks?: any;
|
||||
software_id?: string | undefined;
|
||||
software_version?: string | undefined;
|
||||
software_statement?: string | undefined;
|
||||
client_secret?: string | undefined;
|
||||
client_id_issued_at?: number | undefined;
|
||||
client_secret_expires_at?: number | undefined;
|
||||
} | undefined>;
|
||||
registerClient(clientMetadata: OAuthClientInformationFull): Promise<{
|
||||
redirect_uris: string[];
|
||||
client_id: string;
|
||||
jwks_uri?: string | undefined;
|
||||
scope?: string | undefined;
|
||||
token_endpoint_auth_method?: string | undefined;
|
||||
grant_types?: string[] | undefined;
|
||||
response_types?: string[] | undefined;
|
||||
client_name?: string | undefined;
|
||||
client_uri?: string | undefined;
|
||||
logo_uri?: string | undefined;
|
||||
contacts?: string[] | undefined;
|
||||
tos_uri?: string | undefined;
|
||||
policy_uri?: string | undefined;
|
||||
jwks?: any;
|
||||
software_id?: string | undefined;
|
||||
software_version?: string | undefined;
|
||||
software_statement?: string | undefined;
|
||||
client_secret?: string | undefined;
|
||||
client_id_issued_at?: number | undefined;
|
||||
client_secret_expires_at?: number | undefined;
|
||||
}>;
|
||||
}
|
||||
/**
|
||||
* 🚨 DEMO ONLY - NOT FOR PRODUCTION
|
||||
*
|
||||
* This example demonstrates MCP OAuth flow but lacks some of the features required for production use,
|
||||
* for example:
|
||||
* - Persistent token storage
|
||||
* - Rate limiting
|
||||
*/
|
||||
export declare class DemoInMemoryAuthProvider implements OAuthServerProvider {
|
||||
private validateResource?;
|
||||
clientsStore: DemoInMemoryClientsStore;
|
||||
private codes;
|
||||
private tokens;
|
||||
constructor(validateResource?: ((resource?: URL) => boolean) | undefined);
|
||||
authorize(client: OAuthClientInformationFull, params: AuthorizationParams, res: Response): Promise<void>;
|
||||
challengeForAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string): Promise<string>;
|
||||
exchangeAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string, _codeVerifier?: string): Promise<OAuthTokens>;
|
||||
exchangeRefreshToken(_client: OAuthClientInformationFull, _refreshToken: string, _scopes?: string[], _resource?: URL): Promise<OAuthTokens>;
|
||||
verifyAccessToken(token: string): Promise<AuthInfo>;
|
||||
}
|
||||
export declare const setupAuthServer: ({ authServerUrl, mcpServerUrl, strictResource }: {
|
||||
authServerUrl: URL;
|
||||
mcpServerUrl: URL;
|
||||
strictResource: boolean;
|
||||
}) => OAuthMetadata;
|
||||
//# sourceMappingURL=demoInMemoryOAuthProvider.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/demoInMemoryOAuthProvider.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/demoInMemoryOAuthProvider.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"demoInMemoryOAuthProvider.d.ts","sourceRoot":"","sources":["../../../../src/examples/server/demoInMemoryOAuthProvider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9F,OAAgB,EAAW,QAAQ,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAKtD,qBAAa,wBAAyB,YAAW,2BAA2B;IAC1E,OAAO,CAAC,OAAO,CAAiD;IAE1D,SAAS,CAAC,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;IAI1B,cAAc,CAAC,cAAc,EAAE,0BAA0B;;;;;;;;;;;;;;;;;;;;;;CAIhE;AAED;;;;;;;GAOG;AACH,qBAAa,wBAAyB,YAAW,mBAAmB;IAOtD,OAAO,CAAC,gBAAgB,CAAC;IANrC,YAAY,2BAAkC;IAC9C,OAAO,CAAC,KAAK,CAE4B;IACzC,OAAO,CAAC,MAAM,CAA+B;gBAEzB,gBAAgB,CAAC,GAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,KAAK,OAAO,aAAA;IAE5D,SAAS,CACb,MAAM,EAAE,0BAA0B,EAClC,MAAM,EAAE,mBAAmB,EAC3B,GAAG,EAAE,QAAQ,GACZ,OAAO,CAAC,IAAI,CAAC;IAoBV,6BAA6B,CACjC,MAAM,EAAE,0BAA0B,EAClC,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,MAAM,CAAC;IAWZ,yBAAyB,CAC7B,MAAM,EAAE,0BAA0B,EAClC,iBAAiB,EAAE,MAAM,EAGzB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,WAAW,CAAC;IAoCjB,oBAAoB,CACxB,OAAO,EAAE,0BAA0B,EACnC,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,MAAM,EAAE,EAClB,SAAS,CAAC,EAAE,GAAG,GACd,OAAO,CAAC,WAAW,CAAC;IAIjB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;CAc1D;AAGD,eAAO,MAAM,eAAe,oDAAmD;IAAC,aAAa,EAAE,GAAG,CAAC;IAAC,YAAY,EAAE,GAAG,CAAC;IAAC,cAAc,EAAE,OAAO,CAAA;CAAC,KAAG,aAuEjJ,CAAA"}
|
||||
179
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/demoInMemoryOAuthProvider.js
generated
vendored
Normal file
179
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/demoInMemoryOAuthProvider.js
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.setupAuthServer = exports.DemoInMemoryAuthProvider = exports.DemoInMemoryClientsStore = void 0;
|
||||
const node_crypto_1 = require("node:crypto");
|
||||
const express_1 = __importDefault(require("express"));
|
||||
const router_js_1 = require("../../server/auth/router.js");
|
||||
const auth_utils_js_1 = require("../../shared/auth-utils.js");
|
||||
class DemoInMemoryClientsStore {
|
||||
constructor() {
|
||||
this.clients = new Map();
|
||||
}
|
||||
async getClient(clientId) {
|
||||
return this.clients.get(clientId);
|
||||
}
|
||||
async registerClient(clientMetadata) {
|
||||
this.clients.set(clientMetadata.client_id, clientMetadata);
|
||||
return clientMetadata;
|
||||
}
|
||||
}
|
||||
exports.DemoInMemoryClientsStore = DemoInMemoryClientsStore;
|
||||
/**
|
||||
* 🚨 DEMO ONLY - NOT FOR PRODUCTION
|
||||
*
|
||||
* This example demonstrates MCP OAuth flow but lacks some of the features required for production use,
|
||||
* for example:
|
||||
* - Persistent token storage
|
||||
* - Rate limiting
|
||||
*/
|
||||
class DemoInMemoryAuthProvider {
|
||||
constructor(validateResource) {
|
||||
this.validateResource = validateResource;
|
||||
this.clientsStore = new DemoInMemoryClientsStore();
|
||||
this.codes = new Map();
|
||||
this.tokens = new Map();
|
||||
}
|
||||
async authorize(client, params, res) {
|
||||
const code = (0, node_crypto_1.randomUUID)();
|
||||
const searchParams = new URLSearchParams({
|
||||
code,
|
||||
});
|
||||
if (params.state !== undefined) {
|
||||
searchParams.set('state', params.state);
|
||||
}
|
||||
this.codes.set(code, {
|
||||
client,
|
||||
params
|
||||
});
|
||||
const targetUrl = new URL(client.redirect_uris[0]);
|
||||
targetUrl.search = searchParams.toString();
|
||||
res.redirect(targetUrl.toString());
|
||||
}
|
||||
async challengeForAuthorizationCode(client, authorizationCode) {
|
||||
// Store the challenge with the code data
|
||||
const codeData = this.codes.get(authorizationCode);
|
||||
if (!codeData) {
|
||||
throw new Error('Invalid authorization code');
|
||||
}
|
||||
return codeData.params.codeChallenge;
|
||||
}
|
||||
async exchangeAuthorizationCode(client, authorizationCode,
|
||||
// Note: code verifier is checked in token.ts by default
|
||||
// it's unused here for that reason.
|
||||
_codeVerifier) {
|
||||
const codeData = this.codes.get(authorizationCode);
|
||||
if (!codeData) {
|
||||
throw new Error('Invalid authorization code');
|
||||
}
|
||||
if (codeData.client.client_id !== client.client_id) {
|
||||
throw new Error(`Authorization code was not issued to this client, ${codeData.client.client_id} != ${client.client_id}`);
|
||||
}
|
||||
if (this.validateResource && !this.validateResource(codeData.params.resource)) {
|
||||
throw new Error(`Invalid resource: ${codeData.params.resource}`);
|
||||
}
|
||||
this.codes.delete(authorizationCode);
|
||||
const token = (0, node_crypto_1.randomUUID)();
|
||||
const tokenData = {
|
||||
token,
|
||||
clientId: client.client_id,
|
||||
scopes: codeData.params.scopes || [],
|
||||
expiresAt: Date.now() + 3600000, // 1 hour
|
||||
resource: codeData.params.resource,
|
||||
type: 'access',
|
||||
};
|
||||
this.tokens.set(token, tokenData);
|
||||
return {
|
||||
access_token: token,
|
||||
token_type: 'bearer',
|
||||
expires_in: 3600,
|
||||
scope: (codeData.params.scopes || []).join(' '),
|
||||
};
|
||||
}
|
||||
async exchangeRefreshToken(_client, _refreshToken, _scopes, _resource) {
|
||||
throw new Error('Not implemented for example demo');
|
||||
}
|
||||
async verifyAccessToken(token) {
|
||||
const tokenData = this.tokens.get(token);
|
||||
if (!tokenData || !tokenData.expiresAt || tokenData.expiresAt < Date.now()) {
|
||||
throw new Error('Invalid or expired token');
|
||||
}
|
||||
return {
|
||||
token,
|
||||
clientId: tokenData.clientId,
|
||||
scopes: tokenData.scopes,
|
||||
expiresAt: Math.floor(tokenData.expiresAt / 1000),
|
||||
resource: tokenData.resource,
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.DemoInMemoryAuthProvider = DemoInMemoryAuthProvider;
|
||||
const setupAuthServer = ({ authServerUrl, mcpServerUrl, strictResource }) => {
|
||||
// Create separate auth server app
|
||||
// NOTE: This is a separate app on a separate port to illustrate
|
||||
// how to separate an OAuth Authorization Server from a Resource
|
||||
// server in the SDK. The SDK is not intended to be provide a standalone
|
||||
// authorization server.
|
||||
const validateResource = strictResource ? (resource) => {
|
||||
if (!resource)
|
||||
return false;
|
||||
const expectedResource = (0, auth_utils_js_1.resourceUrlFromServerUrl)(mcpServerUrl);
|
||||
return resource.toString() === expectedResource.toString();
|
||||
} : undefined;
|
||||
const provider = new DemoInMemoryAuthProvider(validateResource);
|
||||
const authApp = (0, express_1.default)();
|
||||
authApp.use(express_1.default.json());
|
||||
// For introspection requests
|
||||
authApp.use(express_1.default.urlencoded());
|
||||
// Add OAuth routes to the auth server
|
||||
// NOTE: this will also add a protected resource metadata route,
|
||||
// but it won't be used, so leave it.
|
||||
authApp.use((0, router_js_1.mcpAuthRouter)({
|
||||
provider,
|
||||
issuerUrl: authServerUrl,
|
||||
scopesSupported: ['mcp:tools'],
|
||||
}));
|
||||
authApp.post('/introspect', async (req, res) => {
|
||||
try {
|
||||
const { token } = req.body;
|
||||
if (!token) {
|
||||
res.status(400).json({ error: 'Token is required' });
|
||||
return;
|
||||
}
|
||||
const tokenInfo = await provider.verifyAccessToken(token);
|
||||
res.json({
|
||||
active: true,
|
||||
client_id: tokenInfo.clientId,
|
||||
scope: tokenInfo.scopes.join(' '),
|
||||
exp: tokenInfo.expiresAt,
|
||||
aud: tokenInfo.resource,
|
||||
});
|
||||
return;
|
||||
}
|
||||
catch (error) {
|
||||
res.status(401).json({
|
||||
active: false,
|
||||
error: 'Unauthorized',
|
||||
error_description: `Invalid token: ${error}`
|
||||
});
|
||||
}
|
||||
});
|
||||
const auth_port = authServerUrl.port;
|
||||
// Start the auth server
|
||||
authApp.listen(auth_port, () => {
|
||||
console.log(`OAuth Authorization Server listening on port ${auth_port}`);
|
||||
});
|
||||
// Note: we could fetch this from the server, but then we end up
|
||||
// with some top level async which gets annoying.
|
||||
const oauthMetadata = (0, router_js_1.createOAuthMetadata)({
|
||||
provider,
|
||||
issuerUrl: authServerUrl,
|
||||
scopesSupported: ['mcp:tools'],
|
||||
});
|
||||
oauthMetadata.introspection_endpoint = new URL("/introspect", authServerUrl).href;
|
||||
return oauthMetadata;
|
||||
};
|
||||
exports.setupAuthServer = setupAuthServer;
|
||||
//# sourceMappingURL=demoInMemoryOAuthProvider.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/demoInMemoryOAuthProvider.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/demoInMemoryOAuthProvider.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/jsonResponseStreamableHttp.d.ts
generated
vendored
Normal file
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/jsonResponseStreamableHttp.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=jsonResponseStreamableHttp.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/jsonResponseStreamableHttp.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/jsonResponseStreamableHttp.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"jsonResponseStreamableHttp.d.ts","sourceRoot":"","sources":["../../../../src/examples/server/jsonResponseStreamableHttp.ts"],"names":[],"mappings":""}
|
||||
142
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/jsonResponseStreamableHttp.js
generated
vendored
Normal file
142
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/jsonResponseStreamableHttp.js
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
"use strict";
|
||||
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 mcp_js_1 = require("../../server/mcp.js");
|
||||
const streamableHttp_js_1 = require("../../server/streamableHttp.js");
|
||||
const zod_1 = require("zod");
|
||||
const types_js_1 = require("../../types.js");
|
||||
// Create an MCP server with implementation details
|
||||
const getServer = () => {
|
||||
const server = new mcp_js_1.McpServer({
|
||||
name: 'json-response-streamable-http-server',
|
||||
version: '1.0.0',
|
||||
}, {
|
||||
capabilities: {
|
||||
logging: {},
|
||||
}
|
||||
});
|
||||
// Register a simple tool that returns a greeting
|
||||
server.tool('greet', 'A simple greeting tool', {
|
||||
name: zod_1.z.string().describe('Name to greet'),
|
||||
}, async ({ name }) => {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Hello, ${name}!`,
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
// Register a tool that sends multiple greetings with notifications
|
||||
server.tool('multi-greet', 'A tool that sends different greetings with delays between them', {
|
||||
name: zod_1.z.string().describe('Name to greet'),
|
||||
}, async ({ name }, { sendNotification }) => {
|
||||
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
await sendNotification({
|
||||
method: "notifications/message",
|
||||
params: { level: "debug", data: `Starting multi-greet for ${name}` }
|
||||
});
|
||||
await sleep(1000); // Wait 1 second before first greeting
|
||||
await sendNotification({
|
||||
method: "notifications/message",
|
||||
params: { level: "info", data: `Sending first greeting to ${name}` }
|
||||
});
|
||||
await sleep(1000); // Wait another second before second greeting
|
||||
await sendNotification({
|
||||
method: "notifications/message",
|
||||
params: { level: "info", data: `Sending second greeting to ${name}` }
|
||||
});
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Good morning, ${name}!`,
|
||||
}
|
||||
],
|
||||
};
|
||||
});
|
||||
return server;
|
||||
};
|
||||
const app = (0, express_1.default)();
|
||||
app.use(express_1.default.json());
|
||||
// Map to store transports by session ID
|
||||
const transports = {};
|
||||
app.post('/mcp', async (req, res) => {
|
||||
console.log('Received MCP request:', req.body);
|
||||
try {
|
||||
// Check for existing session ID
|
||||
const sessionId = req.headers['mcp-session-id'];
|
||||
let transport;
|
||||
if (sessionId && transports[sessionId]) {
|
||||
// Reuse existing transport
|
||||
transport = transports[sessionId];
|
||||
}
|
||||
else if (!sessionId && (0, types_js_1.isInitializeRequest)(req.body)) {
|
||||
// New initialization request - use JSON response mode
|
||||
transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
||||
sessionIdGenerator: () => (0, node_crypto_1.randomUUID)(),
|
||||
enableJsonResponse: true, // Enable JSON response mode
|
||||
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}`);
|
||||
transports[sessionId] = transport;
|
||||
}
|
||||
});
|
||||
// Connect the transport to the MCP server BEFORE handling the request
|
||||
const server = getServer();
|
||||
await server.connect(transport);
|
||||
await transport.handleRequest(req, res, req.body);
|
||||
return; // Already handled
|
||||
}
|
||||
else {
|
||||
// Invalid request - no session ID or not initialization request
|
||||
res.status(400).json({
|
||||
jsonrpc: '2.0',
|
||||
error: {
|
||||
code: -32000,
|
||||
message: 'Bad Request: No valid session ID provided',
|
||||
},
|
||||
id: null,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Handle the request with existing transport - no need to reconnect
|
||||
await transport.handleRequest(req, res, req.body);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error handling MCP request:', error);
|
||||
if (!res.headersSent) {
|
||||
res.status(500).json({
|
||||
jsonrpc: '2.0',
|
||||
error: {
|
||||
code: -32603,
|
||||
message: 'Internal server error',
|
||||
},
|
||||
id: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
// Handle GET requests for SSE streams according to spec
|
||||
app.get('/mcp', async (req, res) => {
|
||||
// Since this is a very simple example, we don't support GET requests for this server
|
||||
// The spec requires returning 405 Method Not Allowed in this case
|
||||
res.status(405).set('Allow', 'POST').send('Method Not Allowed');
|
||||
});
|
||||
// Start the server
|
||||
const PORT = 3000;
|
||||
app.listen(PORT, () => {
|
||||
console.log(`MCP Streamable HTTP Server listening on port ${PORT}`);
|
||||
});
|
||||
// Handle server shutdown
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Shutting down server...');
|
||||
process.exit(0);
|
||||
});
|
||||
//# sourceMappingURL=jsonResponseStreamableHttp.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/jsonResponseStreamableHttp.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/jsonResponseStreamableHttp.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"jsonResponseStreamableHttp.js","sourceRoot":"","sources":["../../../../src/examples/server/jsonResponseStreamableHttp.ts"],"names":[],"mappings":"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"}
|
||||
7
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/mcpServerOutputSchema.d.ts
generated
vendored
Normal file
7
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/mcpServerOutputSchema.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Example MCP server using the high-level McpServer API with outputSchema
|
||||
* This demonstrates how to easily create tools with structured output
|
||||
*/
|
||||
export {};
|
||||
//# sourceMappingURL=mcpServerOutputSchema.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/mcpServerOutputSchema.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/mcpServerOutputSchema.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"mcpServerOutputSchema.d.ts","sourceRoot":"","sources":["../../../../src/examples/server/mcpServerOutputSchema.ts"],"names":[],"mappings":";AACA;;;GAGG"}
|
||||
70
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/mcpServerOutputSchema.js
generated
vendored
Normal file
70
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/mcpServerOutputSchema.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
/**
|
||||
* Example MCP server using the high-level McpServer API with outputSchema
|
||||
* This demonstrates how to easily create tools with structured output
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const mcp_js_1 = require("../../server/mcp.js");
|
||||
const stdio_js_1 = require("../../server/stdio.js");
|
||||
const zod_1 = require("zod");
|
||||
const server = new mcp_js_1.McpServer({
|
||||
name: "mcp-output-schema-high-level-example",
|
||||
version: "1.0.0",
|
||||
});
|
||||
// Define a tool with structured output - Weather data
|
||||
server.registerTool("get_weather", {
|
||||
description: "Get weather information for a city",
|
||||
inputSchema: {
|
||||
city: zod_1.z.string().describe("City name"),
|
||||
country: zod_1.z.string().describe("Country code (e.g., US, UK)")
|
||||
},
|
||||
outputSchema: {
|
||||
temperature: zod_1.z.object({
|
||||
celsius: zod_1.z.number(),
|
||||
fahrenheit: zod_1.z.number()
|
||||
}),
|
||||
conditions: zod_1.z.enum(["sunny", "cloudy", "rainy", "stormy", "snowy"]),
|
||||
humidity: zod_1.z.number().min(0).max(100),
|
||||
wind: zod_1.z.object({
|
||||
speed_kmh: zod_1.z.number(),
|
||||
direction: zod_1.z.string()
|
||||
})
|
||||
},
|
||||
}, async ({ city, country }) => {
|
||||
// Parameters are available but not used in this example
|
||||
void city;
|
||||
void country;
|
||||
// Simulate weather API call
|
||||
const temp_c = Math.round((Math.random() * 35 - 5) * 10) / 10;
|
||||
const conditions = ["sunny", "cloudy", "rainy", "stormy", "snowy"][Math.floor(Math.random() * 5)];
|
||||
const structuredContent = {
|
||||
temperature: {
|
||||
celsius: temp_c,
|
||||
fahrenheit: Math.round((temp_c * 9 / 5 + 32) * 10) / 10
|
||||
},
|
||||
conditions,
|
||||
humidity: Math.round(Math.random() * 100),
|
||||
wind: {
|
||||
speed_kmh: Math.round(Math.random() * 50),
|
||||
direction: ["N", "NE", "E", "SE", "S", "SW", "W", "NW"][Math.floor(Math.random() * 8)]
|
||||
}
|
||||
};
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: JSON.stringify(structuredContent, null, 2)
|
||||
}],
|
||||
structuredContent
|
||||
};
|
||||
});
|
||||
async function main() {
|
||||
const transport = new stdio_js_1.StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
console.error("High-level Output Schema Example Server running on stdio");
|
||||
}
|
||||
main().catch((error) => {
|
||||
console.error("Server error:", error);
|
||||
process.exit(1);
|
||||
});
|
||||
//# sourceMappingURL=mcpServerOutputSchema.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/mcpServerOutputSchema.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/mcpServerOutputSchema.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"mcpServerOutputSchema.js","sourceRoot":"","sources":["../../../../src/examples/server/mcpServerOutputSchema.ts"],"names":[],"mappings":"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"}
|
||||
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleSseServer.d.ts
generated
vendored
Normal file
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleSseServer.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=simpleSseServer.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleSseServer.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleSseServer.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"simpleSseServer.d.ts","sourceRoot":"","sources":["../../../../src/examples/server/simpleSseServer.ts"],"names":[],"mappings":""}
|
||||
148
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleSseServer.js
generated
vendored
Normal file
148
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleSseServer.js
generated
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
"use strict";
|
||||
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 mcp_js_1 = require("../../server/mcp.js");
|
||||
const sse_js_1 = require("../../server/sse.js");
|
||||
const zod_1 = require("zod");
|
||||
/**
|
||||
* This example server demonstrates the deprecated HTTP+SSE transport
|
||||
* (protocol version 2024-11-05). It mainly used for testing backward compatible clients.
|
||||
*
|
||||
* The server exposes two endpoints:
|
||||
* - /mcp: For establishing the SSE stream (GET)
|
||||
* - /messages: For receiving client messages (POST)
|
||||
*
|
||||
*/
|
||||
// Create an MCP server instance
|
||||
const getServer = () => {
|
||||
const server = new mcp_js_1.McpServer({
|
||||
name: 'simple-sse-server',
|
||||
version: '1.0.0',
|
||||
}, { capabilities: { logging: {} } });
|
||||
server.tool('start-notification-stream', 'Starts sending periodic notifications', {
|
||||
interval: zod_1.z.number().describe('Interval in milliseconds between notifications').default(1000),
|
||||
count: zod_1.z.number().describe('Number of notifications to send').default(10),
|
||||
}, async ({ interval, count }, { sendNotification }) => {
|
||||
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
let counter = 0;
|
||||
// Send the initial notification
|
||||
await sendNotification({
|
||||
method: "notifications/message",
|
||||
params: {
|
||||
level: "info",
|
||||
data: `Starting notification stream with ${count} messages every ${interval}ms`
|
||||
}
|
||||
});
|
||||
// Send periodic notifications
|
||||
while (counter < count) {
|
||||
counter++;
|
||||
await sleep(interval);
|
||||
try {
|
||||
await sendNotification({
|
||||
method: "notifications/message",
|
||||
params: {
|
||||
level: "info",
|
||||
data: `Notification #${counter} at ${new Date().toISOString()}`
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
console.error("Error sending notification:", error);
|
||||
}
|
||||
}
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Completed sending ${count} notifications every ${interval}ms`,
|
||||
}
|
||||
],
|
||||
};
|
||||
});
|
||||
return server;
|
||||
};
|
||||
const app = (0, express_1.default)();
|
||||
app.use(express_1.default.json());
|
||||
// Store transports by session ID
|
||||
const transports = {};
|
||||
// SSE endpoint for establishing the stream
|
||||
app.get('/mcp', async (req, res) => {
|
||||
console.log('Received GET request to /sse (establishing SSE stream)');
|
||||
try {
|
||||
// Create a new SSE transport for the client
|
||||
// The endpoint for POST messages is '/messages'
|
||||
const transport = new sse_js_1.SSEServerTransport('/messages', res);
|
||||
// Store the transport by session ID
|
||||
const sessionId = transport.sessionId;
|
||||
transports[sessionId] = transport;
|
||||
// Set up onclose handler to clean up transport when closed
|
||||
transport.onclose = () => {
|
||||
console.log(`SSE transport closed for session ${sessionId}`);
|
||||
delete transports[sessionId];
|
||||
};
|
||||
// Connect the transport to the MCP server
|
||||
const server = getServer();
|
||||
await server.connect(transport);
|
||||
console.log(`Established SSE stream with session ID: ${sessionId}`);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error establishing SSE stream:', error);
|
||||
if (!res.headersSent) {
|
||||
res.status(500).send('Error establishing SSE stream');
|
||||
}
|
||||
}
|
||||
});
|
||||
// Messages endpoint for receiving client JSON-RPC requests
|
||||
app.post('/messages', async (req, res) => {
|
||||
console.log('Received POST request to /messages');
|
||||
// Extract session ID from URL query parameter
|
||||
// In the SSE protocol, this is added by the client based on the endpoint event
|
||||
const sessionId = req.query.sessionId;
|
||||
if (!sessionId) {
|
||||
console.error('No session ID provided in request URL');
|
||||
res.status(400).send('Missing sessionId parameter');
|
||||
return;
|
||||
}
|
||||
const transport = transports[sessionId];
|
||||
if (!transport) {
|
||||
console.error(`No active transport found for session ID: ${sessionId}`);
|
||||
res.status(404).send('Session not found');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Handle the POST message with the transport
|
||||
await transport.handlePostMessage(req, res, req.body);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error handling request:', error);
|
||||
if (!res.headersSent) {
|
||||
res.status(500).send('Error handling request');
|
||||
}
|
||||
}
|
||||
});
|
||||
// Start the server
|
||||
const PORT = 3000;
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Simple SSE Server (deprecated protocol version 2024-11-05) listening on port ${PORT}`);
|
||||
});
|
||||
// Handle server shutdown
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Shutting down server...');
|
||||
// Close all active transports to properly clean up resources
|
||||
for (const sessionId in transports) {
|
||||
try {
|
||||
console.log(`Closing transport for session ${sessionId}`);
|
||||
await transports[sessionId].close();
|
||||
delete transports[sessionId];
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`Error closing transport for session ${sessionId}:`, error);
|
||||
}
|
||||
}
|
||||
console.log('Server shutdown complete');
|
||||
process.exit(0);
|
||||
});
|
||||
//# sourceMappingURL=simpleSseServer.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleSseServer.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleSseServer.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"simpleSseServer.js","sourceRoot":"","sources":["../../../../src/examples/server/simpleSseServer.ts"],"names":[],"mappings":"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"}
|
||||
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStatelessStreamableHttp.d.ts
generated
vendored
Normal file
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStatelessStreamableHttp.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=simpleStatelessStreamableHttp.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStatelessStreamableHttp.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStatelessStreamableHttp.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"simpleStatelessStreamableHttp.d.ts","sourceRoot":"","sources":["../../../../src/examples/server/simpleStatelessStreamableHttp.ts"],"names":[],"mappings":""}
|
||||
140
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStatelessStreamableHttp.js
generated
vendored
Normal file
140
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStatelessStreamableHttp.js
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
"use strict";
|
||||
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 mcp_js_1 = require("../../server/mcp.js");
|
||||
const streamableHttp_js_1 = require("../../server/streamableHttp.js");
|
||||
const zod_1 = require("zod");
|
||||
const getServer = () => {
|
||||
// Create an MCP server with implementation details
|
||||
const server = new mcp_js_1.McpServer({
|
||||
name: 'stateless-streamable-http-server',
|
||||
version: '1.0.0',
|
||||
}, { capabilities: { logging: {} } });
|
||||
// Register a simple prompt
|
||||
server.prompt('greeting-template', 'A simple greeting prompt template', {
|
||||
name: zod_1.z.string().describe('Name to include in greeting'),
|
||||
}, async ({ name }) => {
|
||||
return {
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
content: {
|
||||
type: 'text',
|
||||
text: `Please greet ${name} in a friendly manner.`,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
// Register a tool specifically for testing resumability
|
||||
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(10),
|
||||
}, async ({ interval, count }, { sendNotification }) => {
|
||||
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
let counter = 0;
|
||||
while (count === 0 || counter < count) {
|
||||
counter++;
|
||||
try {
|
||||
await sendNotification({
|
||||
method: "notifications/message",
|
||||
params: {
|
||||
level: "info",
|
||||
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
console.error("Error sending notification:", error);
|
||||
}
|
||||
// Wait for the specified interval
|
||||
await sleep(interval);
|
||||
}
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Started sending periodic notifications every ${interval}ms`,
|
||||
}
|
||||
],
|
||||
};
|
||||
});
|
||||
// Create a simple resource at a fixed URI
|
||||
server.resource('greeting-resource', 'https://example.com/greetings/default', { mimeType: 'text/plain' }, async () => {
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
uri: 'https://example.com/greetings/default',
|
||||
text: 'Hello, world!',
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
return server;
|
||||
};
|
||||
const app = (0, express_1.default)();
|
||||
app.use(express_1.default.json());
|
||||
app.post('/mcp', async (req, res) => {
|
||||
const server = getServer();
|
||||
try {
|
||||
const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
||||
sessionIdGenerator: undefined,
|
||||
});
|
||||
await server.connect(transport);
|
||||
await transport.handleRequest(req, res, req.body);
|
||||
res.on('close', () => {
|
||||
console.log('Request closed');
|
||||
transport.close();
|
||||
server.close();
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error handling MCP request:', error);
|
||||
if (!res.headersSent) {
|
||||
res.status(500).json({
|
||||
jsonrpc: '2.0',
|
||||
error: {
|
||||
code: -32603,
|
||||
message: 'Internal server error',
|
||||
},
|
||||
id: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
app.get('/mcp', async (req, res) => {
|
||||
console.log('Received GET MCP request');
|
||||
res.writeHead(405).end(JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
error: {
|
||||
code: -32000,
|
||||
message: "Method not allowed."
|
||||
},
|
||||
id: null
|
||||
}));
|
||||
});
|
||||
app.delete('/mcp', async (req, res) => {
|
||||
console.log('Received DELETE MCP request');
|
||||
res.writeHead(405).end(JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
error: {
|
||||
code: -32000,
|
||||
message: "Method not allowed."
|
||||
},
|
||||
id: null
|
||||
}));
|
||||
});
|
||||
// Start the server
|
||||
const PORT = 3000;
|
||||
app.listen(PORT, () => {
|
||||
console.log(`MCP Stateless Streamable HTTP Server listening on port ${PORT}`);
|
||||
});
|
||||
// Handle server shutdown
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Shutting down server...');
|
||||
process.exit(0);
|
||||
});
|
||||
//# sourceMappingURL=simpleStatelessStreamableHttp.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStatelessStreamableHttp.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStatelessStreamableHttp.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"simpleStatelessStreamableHttp.js","sourceRoot":"","sources":["../../../../src/examples/server/simpleStatelessStreamableHttp.ts"],"names":[],"mappings":"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"}
|
||||
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStreamableHttp.d.ts
generated
vendored
Normal file
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStreamableHttp.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=simpleStreamableHttp.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStreamableHttp.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStreamableHttp.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"simpleStreamableHttp.d.ts","sourceRoot":"","sources":["../../../../src/examples/server/simpleStreamableHttp.ts"],"names":[],"mappings":""}
|
||||
578
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStreamableHttp.js
generated
vendored
Normal file
578
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStreamableHttp.js
generated
vendored
Normal file
@@ -0,0 +1,578 @@
|
||||
"use strict";
|
||||
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 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 types_js_1 = require("../../types.js");
|
||||
const inMemoryEventStore_js_1 = require("../shared/inMemoryEventStore.js");
|
||||
const demoInMemoryOAuthProvider_js_1 = require("./demoInMemoryOAuthProvider.js");
|
||||
const auth_utils_js_1 = require("src/shared/auth-utils.js");
|
||||
// Check for OAuth flag
|
||||
const useOAuth = process.argv.includes('--oauth');
|
||||
const strictOAuth = process.argv.includes('--oauth-strict');
|
||||
// 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'
|
||||
}, { 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: zod_1.z.string().describe('Name to greet'),
|
||||
},
|
||||
}, async ({ name }) => {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Hello, ${name}!`,
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
// Register a tool that sends multiple greetings with notifications (with annotations)
|
||||
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 sendNotification({
|
||||
method: "notifications/message",
|
||||
params: { level: "debug", data: `Starting multi-greet for ${name}` }
|
||||
});
|
||||
await sleep(1000); // Wait 1 second before first greeting
|
||||
await sendNotification({
|
||||
method: "notifications/message",
|
||||
params: { level: "info", data: `Sending first greeting to ${name}` }
|
||||
});
|
||||
await sleep(1000); // Wait another second before second greeting
|
||||
await sendNotification({
|
||||
method: "notifications/message",
|
||||
params: { level: "info", data: `Sending second greeting to ${name}` }
|
||||
});
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Good morning, ${name}!`,
|
||||
}
|
||||
],
|
||||
};
|
||||
});
|
||||
// Register a tool that demonstrates elicitation (user input collection)
|
||||
// This creates a closure that captures the server instance
|
||||
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) {
|
||||
case 'contact':
|
||||
message = 'Please provide your contact information';
|
||||
requestedSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
title: 'Full Name',
|
||||
description: 'Your full name',
|
||||
},
|
||||
email: {
|
||||
type: 'string',
|
||||
title: 'Email Address',
|
||||
description: 'Your email address',
|
||||
format: 'email',
|
||||
},
|
||||
phone: {
|
||||
type: 'string',
|
||||
title: 'Phone Number',
|
||||
description: 'Your phone number (optional)',
|
||||
},
|
||||
},
|
||||
required: ['name', 'email'],
|
||||
};
|
||||
break;
|
||||
case 'preferences':
|
||||
message = 'Please set your preferences';
|
||||
requestedSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
theme: {
|
||||
type: 'string',
|
||||
title: 'Theme',
|
||||
description: 'Choose your preferred theme',
|
||||
enum: ['light', 'dark', 'auto'],
|
||||
enumNames: ['Light', 'Dark', 'Auto'],
|
||||
},
|
||||
notifications: {
|
||||
type: 'boolean',
|
||||
title: 'Enable Notifications',
|
||||
description: 'Would you like to receive notifications?',
|
||||
default: true,
|
||||
},
|
||||
frequency: {
|
||||
type: 'string',
|
||||
title: 'Notification Frequency',
|
||||
description: 'How often would you like notifications?',
|
||||
enum: ['daily', 'weekly', 'monthly'],
|
||||
enumNames: ['Daily', 'Weekly', 'Monthly'],
|
||||
},
|
||||
},
|
||||
required: ['theme'],
|
||||
};
|
||||
break;
|
||||
case 'feedback':
|
||||
message = 'Please provide your feedback';
|
||||
requestedSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
rating: {
|
||||
type: 'integer',
|
||||
title: 'Rating',
|
||||
description: 'Rate your experience (1-5)',
|
||||
minimum: 1,
|
||||
maximum: 5,
|
||||
},
|
||||
comments: {
|
||||
type: 'string',
|
||||
title: 'Comments',
|
||||
description: 'Additional comments (optional)',
|
||||
maxLength: 500,
|
||||
},
|
||||
recommend: {
|
||||
type: 'boolean',
|
||||
title: 'Would you recommend this?',
|
||||
description: 'Would you recommend this to others?',
|
||||
},
|
||||
},
|
||||
required: ['rating', 'recommend'],
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown info type: ${infoType}`);
|
||||
}
|
||||
try {
|
||||
// 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)}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
else if (result.action === 'decline') {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `No information was collected. User declined ${infoType} information request.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
else {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Information collection was cancelled by the user.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Error collecting ${infoType} information: ${error}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
});
|
||||
// Register a simple prompt with title
|
||||
server.registerPrompt('greeting-template', {
|
||||
title: 'Greeting Template', // Display name for UI
|
||||
description: 'A simple greeting prompt template',
|
||||
argsSchema: {
|
||||
name: zod_1.z.string().describe('Name to include in greeting'),
|
||||
},
|
||||
}, async ({ name }) => {
|
||||
return {
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
content: {
|
||||
type: 'text',
|
||||
text: `Please greet ${name} in a friendly manner.`,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
// Register a tool specifically for testing resumability
|
||||
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 sendNotification({
|
||||
method: "notifications/message",
|
||||
params: {
|
||||
level: "info",
|
||||
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
console.error("Error sending notification:", error);
|
||||
}
|
||||
// Wait for the specified interval
|
||||
await sleep(interval);
|
||||
}
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Started sending periodic notifications every ${interval}ms`,
|
||||
}
|
||||
],
|
||||
};
|
||||
});
|
||||
// Create a simple resource at a fixed URI
|
||||
server.registerResource('greeting-resource', 'https://example.com/greetings/default', {
|
||||
title: 'Default Greeting', // Display name for UI
|
||||
description: 'A simple greeting resource',
|
||||
mimeType: 'text/plain'
|
||||
}, async () => {
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
uri: 'https://example.com/greetings/default',
|
||||
text: 'Hello, world!',
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
// Create additional resources for ResourceLink demonstration
|
||||
server.registerResource('example-file-1', 'file:///example/file1.txt', {
|
||||
title: 'Example File 1',
|
||||
description: 'First example file for ResourceLink demonstration',
|
||||
mimeType: 'text/plain'
|
||||
}, async () => {
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
uri: 'file:///example/file1.txt',
|
||||
text: 'This is the content of file 1',
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
server.registerResource('example-file-2', 'file:///example/file2.txt', {
|
||||
title: 'Example File 2',
|
||||
description: 'Second example file for ResourceLink demonstration',
|
||||
mimeType: 'text/plain'
|
||||
}, async () => {
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
uri: 'file:///example/file2.txt',
|
||||
text: 'This is the content of file 2',
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
// Register a tool that returns ResourceLinks
|
||||
server.registerTool('list-files', {
|
||||
title: 'List Files with ResourceLinks',
|
||||
description: 'Returns a list of files as ResourceLinks without embedding their content',
|
||||
inputSchema: {
|
||||
includeDescriptions: zod_1.z.boolean().optional().describe('Whether to include descriptions in the resource links'),
|
||||
},
|
||||
}, async ({ includeDescriptions = true }) => {
|
||||
const resourceLinks = [
|
||||
{
|
||||
type: 'resource_link',
|
||||
uri: 'https://example.com/greetings/default',
|
||||
name: 'Default Greeting',
|
||||
mimeType: 'text/plain',
|
||||
...(includeDescriptions && { description: 'A simple greeting resource' })
|
||||
},
|
||||
{
|
||||
type: 'resource_link',
|
||||
uri: 'file:///example/file1.txt',
|
||||
name: 'Example File 1',
|
||||
mimeType: 'text/plain',
|
||||
...(includeDescriptions && { description: 'First example file for ResourceLink demonstration' })
|
||||
},
|
||||
{
|
||||
type: 'resource_link',
|
||||
uri: 'file:///example/file2.txt',
|
||||
name: 'Example File 2',
|
||||
mimeType: 'text/plain',
|
||||
...(includeDescriptions && { description: 'Second example file for ResourceLink demonstration' })
|
||||
}
|
||||
];
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'Here are the available files as resource links:',
|
||||
},
|
||||
...resourceLinks,
|
||||
{
|
||||
type: 'text',
|
||||
text: '\nYou can read any of these resources using their URI.',
|
||||
}
|
||||
],
|
||||
};
|
||||
});
|
||||
return server;
|
||||
};
|
||||
const MCP_PORT = 3000;
|
||||
const AUTH_PORT = 3001;
|
||||
const app = (0, express_1.default)();
|
||||
app.use(express_1.default.json());
|
||||
// Set up OAuth if enabled
|
||||
let authMiddleware = null;
|
||||
if (useOAuth) {
|
||||
// Create auth middleware for MCP endpoints
|
||||
const mcpServerUrl = new URL(`http://localhost:${MCP_PORT}/mcp`);
|
||||
const authServerUrl = new URL(`http://localhost:${AUTH_PORT}`);
|
||||
const oauthMetadata = (0, demoInMemoryOAuthProvider_js_1.setupAuthServer)({ authServerUrl, mcpServerUrl, strictResource: strictOAuth });
|
||||
const tokenVerifier = {
|
||||
verifyAccessToken: async (token) => {
|
||||
const endpoint = oauthMetadata.introspection_endpoint;
|
||||
if (!endpoint) {
|
||||
throw new Error('No token verification endpoint available in metadata');
|
||||
}
|
||||
const response = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
token: token
|
||||
}).toString()
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Invalid or expired token: ${await response.text()}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
if (strictOAuth) {
|
||||
if (!data.aud) {
|
||||
throw new Error(`Resource Indicator (RFC8707) missing`);
|
||||
}
|
||||
if (!(0, auth_utils_js_1.checkResourceAllowed)({ requestedResource: data.aud, configuredResource: mcpServerUrl })) {
|
||||
throw new Error(`Expected resource indicator ${mcpServerUrl}, got: ${data.aud}`);
|
||||
}
|
||||
}
|
||||
// Convert the response to AuthInfo format
|
||||
return {
|
||||
token,
|
||||
clientId: data.client_id,
|
||||
scopes: data.scope ? data.scope.split(' ') : [],
|
||||
expiresAt: data.exp,
|
||||
};
|
||||
}
|
||||
};
|
||||
// Add metadata routes to the main MCP server
|
||||
app.use((0, router_js_1.mcpAuthMetadataRouter)({
|
||||
oauthMetadata,
|
||||
resourceServerUrl: mcpServerUrl,
|
||||
scopesSupported: ['mcp:tools'],
|
||||
resourceName: 'MCP Demo Server',
|
||||
}));
|
||||
authMiddleware = (0, bearerAuth_js_1.requireBearerAuth)({
|
||||
verifier: tokenVerifier,
|
||||
requiredScopes: [],
|
||||
resourceMetadataUrl: (0, router_js_1.getOAuthProtectedResourceMetadataUrl)(mcpServerUrl),
|
||||
});
|
||||
}
|
||||
// Map to store transports by session ID
|
||||
const transports = {};
|
||||
// MCP POST endpoint with optional auth
|
||||
const mcpPostHandler = async (req, res) => {
|
||||
const sessionId = req.headers['mcp-session-id'];
|
||||
if (sessionId) {
|
||||
console.log(`Received MCP request for session: ${sessionId}`);
|
||||
}
|
||||
else {
|
||||
console.log('Request body:', req.body);
|
||||
}
|
||||
if (useOAuth && req.auth) {
|
||||
console.log('Authenticated user:', req.auth);
|
||||
}
|
||||
try {
|
||||
let transport;
|
||||
if (sessionId && transports[sessionId]) {
|
||||
// Reuse existing transport
|
||||
transport = transports[sessionId];
|
||||
}
|
||||
else if (!sessionId && (0, types_js_1.isInitializeRequest)(req.body)) {
|
||||
// New initialization request
|
||||
const eventStore = new inMemoryEventStore_js_1.InMemoryEventStore();
|
||||
transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
||||
sessionIdGenerator: () => (0, node_crypto_1.randomUUID)(),
|
||||
eventStore, // Enable resumability
|
||||
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}`);
|
||||
transports[sessionId] = transport;
|
||||
}
|
||||
});
|
||||
// Set up onclose handler to clean up transport when closed
|
||||
transport.onclose = () => {
|
||||
const sid = transport.sessionId;
|
||||
if (sid && transports[sid]) {
|
||||
console.log(`Transport closed for session ${sid}, removing from transports map`);
|
||||
delete transports[sid];
|
||||
}
|
||||
};
|
||||
// Connect the transport to the MCP server BEFORE handling the request
|
||||
// so responses can flow back through the same transport
|
||||
const server = getServer();
|
||||
await server.connect(transport);
|
||||
await transport.handleRequest(req, res, req.body);
|
||||
return; // Already handled
|
||||
}
|
||||
else {
|
||||
// Invalid request - no session ID or not initialization request
|
||||
res.status(400).json({
|
||||
jsonrpc: '2.0',
|
||||
error: {
|
||||
code: -32000,
|
||||
message: 'Bad Request: No valid session ID provided',
|
||||
},
|
||||
id: null,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Handle the request with existing transport - no need to reconnect
|
||||
// The existing transport is already connected to the server
|
||||
await transport.handleRequest(req, res, req.body);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error handling MCP request:', error);
|
||||
if (!res.headersSent) {
|
||||
res.status(500).json({
|
||||
jsonrpc: '2.0',
|
||||
error: {
|
||||
code: -32603,
|
||||
message: 'Internal server error',
|
||||
},
|
||||
id: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
// Set up routes with conditional auth middleware
|
||||
if (useOAuth && authMiddleware) {
|
||||
app.post('/mcp', authMiddleware, mcpPostHandler);
|
||||
}
|
||||
else {
|
||||
app.post('/mcp', mcpPostHandler);
|
||||
}
|
||||
// Handle GET requests for SSE streams (using built-in support from StreamableHTTP)
|
||||
const mcpGetHandler = async (req, res) => {
|
||||
const sessionId = req.headers['mcp-session-id'];
|
||||
if (!sessionId || !transports[sessionId]) {
|
||||
res.status(400).send('Invalid or missing session ID');
|
||||
return;
|
||||
}
|
||||
if (useOAuth && req.auth) {
|
||||
console.log('Authenticated SSE connection from user:', req.auth);
|
||||
}
|
||||
// Check for Last-Event-ID header for resumability
|
||||
const lastEventId = req.headers['last-event-id'];
|
||||
if (lastEventId) {
|
||||
console.log(`Client reconnecting with Last-Event-ID: ${lastEventId}`);
|
||||
}
|
||||
else {
|
||||
console.log(`Establishing new SSE stream for session ${sessionId}`);
|
||||
}
|
||||
const transport = transports[sessionId];
|
||||
await transport.handleRequest(req, res);
|
||||
};
|
||||
// Set up GET route with conditional auth middleware
|
||||
if (useOAuth && authMiddleware) {
|
||||
app.get('/mcp', authMiddleware, mcpGetHandler);
|
||||
}
|
||||
else {
|
||||
app.get('/mcp', mcpGetHandler);
|
||||
}
|
||||
// Handle DELETE requests for session termination (according to MCP spec)
|
||||
const mcpDeleteHandler = async (req, res) => {
|
||||
const sessionId = req.headers['mcp-session-id'];
|
||||
if (!sessionId || !transports[sessionId]) {
|
||||
res.status(400).send('Invalid or missing session ID');
|
||||
return;
|
||||
}
|
||||
console.log(`Received session termination request for session ${sessionId}`);
|
||||
try {
|
||||
const transport = transports[sessionId];
|
||||
await transport.handleRequest(req, res);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error handling session termination:', error);
|
||||
if (!res.headersSent) {
|
||||
res.status(500).send('Error processing session termination');
|
||||
}
|
||||
}
|
||||
};
|
||||
// Set up DELETE route with conditional auth middleware
|
||||
if (useOAuth && authMiddleware) {
|
||||
app.delete('/mcp', authMiddleware, mcpDeleteHandler);
|
||||
}
|
||||
else {
|
||||
app.delete('/mcp', mcpDeleteHandler);
|
||||
}
|
||||
app.listen(MCP_PORT, () => {
|
||||
console.log(`MCP Streamable HTTP Server listening on port ${MCP_PORT}`);
|
||||
});
|
||||
// Handle server shutdown
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Shutting down server...');
|
||||
// Close all active transports to properly clean up resources
|
||||
for (const sessionId in transports) {
|
||||
try {
|
||||
console.log(`Closing transport for session ${sessionId}`);
|
||||
await transports[sessionId].close();
|
||||
delete transports[sessionId];
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`Error closing transport for session ${sessionId}:`, error);
|
||||
}
|
||||
}
|
||||
console.log('Server shutdown complete');
|
||||
process.exit(0);
|
||||
});
|
||||
//# sourceMappingURL=simpleStreamableHttp.js.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStreamableHttp.js.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/simpleStreamableHttp.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/sseAndStreamableHttpCompatibleServer.d.ts
generated
vendored
Normal file
2
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/sseAndStreamableHttpCompatibleServer.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=sseAndStreamableHttpCompatibleServer.d.ts.map
|
||||
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/sseAndStreamableHttpCompatibleServer.d.ts.map
generated
vendored
Normal file
1
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/sseAndStreamableHttpCompatibleServer.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"sseAndStreamableHttpCompatibleServer.d.ts","sourceRoot":"","sources":["../../../../src/examples/server/sseAndStreamableHttpCompatibleServer.ts"],"names":[],"mappings":""}
|
||||
233
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/sseAndStreamableHttpCompatibleServer.js
generated
vendored
Normal file
233
mcp-server/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/sseAndStreamableHttpCompatibleServer.js
generated
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
"use strict";
|
||||
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 mcp_js_1 = require("../../server/mcp.js");
|
||||
const streamableHttp_js_1 = require("../../server/streamableHttp.js");
|
||||
const sse_js_1 = require("../../server/sse.js");
|
||||
const zod_1 = require("zod");
|
||||
const types_js_1 = require("../../types.js");
|
||||
const inMemoryEventStore_js_1 = require("../shared/inMemoryEventStore.js");
|
||||
/**
|
||||
* This example server demonstrates backwards compatibility with both:
|
||||
* 1. The deprecated HTTP+SSE transport (protocol version 2024-11-05)
|
||||
* 2. The Streamable HTTP transport (protocol version 2025-03-26)
|
||||
*
|
||||
* It maintains a single MCP server instance but exposes two transport options:
|
||||
* - /mcp: The new Streamable HTTP endpoint (supports GET/POST/DELETE)
|
||||
* - /sse: The deprecated SSE endpoint for older clients (GET to establish stream)
|
||||
* - /messages: The deprecated POST endpoint for older clients (POST to send messages)
|
||||
*/
|
||||
const getServer = () => {
|
||||
const server = new mcp_js_1.McpServer({
|
||||
name: 'backwards-compatible-server',
|
||||
version: '1.0.0',
|
||||
}, { capabilities: { logging: {} } });
|
||||
// Register a simple tool that sends notifications over time
|
||||
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 sendNotification({
|
||||
method: "notifications/message",
|
||||
params: {
|
||||
level: "info",
|
||||
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
console.error("Error sending notification:", error);
|
||||
}
|
||||
// Wait for the specified interval
|
||||
await sleep(interval);
|
||||
}
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Started sending periodic notifications every ${interval}ms`,
|
||||
}
|
||||
],
|
||||
};
|
||||
});
|
||||
return server;
|
||||
};
|
||||
// Create Express application
|
||||
const app = (0, express_1.default)();
|
||||
app.use(express_1.default.json());
|
||||
// Store transports by session ID
|
||||
const transports = {};
|
||||
//=============================================================================
|
||||
// STREAMABLE HTTP TRANSPORT (PROTOCOL VERSION 2025-03-26)
|
||||
//=============================================================================
|
||||
// Handle all MCP Streamable HTTP requests (GET, POST, DELETE) on a single endpoint
|
||||
app.all('/mcp', async (req, res) => {
|
||||
console.log(`Received ${req.method} request to /mcp`);
|
||||
try {
|
||||
// Check for existing session ID
|
||||
const sessionId = req.headers['mcp-session-id'];
|
||||
let transport;
|
||||
if (sessionId && transports[sessionId]) {
|
||||
// Check if the transport is of the correct type
|
||||
const existingTransport = transports[sessionId];
|
||||
if (existingTransport instanceof streamableHttp_js_1.StreamableHTTPServerTransport) {
|
||||
// Reuse existing transport
|
||||
transport = existingTransport;
|
||||
}
|
||||
else {
|
||||
// Transport exists but is not a StreamableHTTPServerTransport (could be SSEServerTransport)
|
||||
res.status(400).json({
|
||||
jsonrpc: '2.0',
|
||||
error: {
|
||||
code: -32000,
|
||||
message: 'Bad Request: Session exists but uses a different transport protocol',
|
||||
},
|
||||
id: null,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!sessionId && req.method === 'POST' && (0, types_js_1.isInitializeRequest)(req.body)) {
|
||||
const eventStore = new inMemoryEventStore_js_1.InMemoryEventStore();
|
||||
transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
||||
sessionIdGenerator: () => (0, node_crypto_1.randomUUID)(),
|
||||
eventStore, // Enable resumability
|
||||
onsessioninitialized: (sessionId) => {
|
||||
// Store the transport by session ID when session is initialized
|
||||
console.log(`StreamableHTTP session initialized with ID: ${sessionId}`);
|
||||
transports[sessionId] = transport;
|
||||
}
|
||||
});
|
||||
// Set up onclose handler to clean up transport when closed
|
||||
transport.onclose = () => {
|
||||
const sid = transport.sessionId;
|
||||
if (sid && transports[sid]) {
|
||||
console.log(`Transport closed for session ${sid}, removing from transports map`);
|
||||
delete transports[sid];
|
||||
}
|
||||
};
|
||||
// Connect the transport to the MCP server
|
||||
const server = getServer();
|
||||
await server.connect(transport);
|
||||
}
|
||||
else {
|
||||
// Invalid request - no session ID or not initialization request
|
||||
res.status(400).json({
|
||||
jsonrpc: '2.0',
|
||||
error: {
|
||||
code: -32000,
|
||||
message: 'Bad Request: No valid session ID provided',
|
||||
},
|
||||
id: null,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Handle the request with the transport
|
||||
await transport.handleRequest(req, res, req.body);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error handling MCP request:', error);
|
||||
if (!res.headersSent) {
|
||||
res.status(500).json({
|
||||
jsonrpc: '2.0',
|
||||
error: {
|
||||
code: -32603,
|
||||
message: 'Internal server error',
|
||||
},
|
||||
id: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
//=============================================================================
|
||||
// DEPRECATED HTTP+SSE TRANSPORT (PROTOCOL VERSION 2024-11-05)
|
||||
//=============================================================================
|
||||
app.get('/sse', async (req, res) => {
|
||||
console.log('Received GET request to /sse (deprecated SSE transport)');
|
||||
const transport = new sse_js_1.SSEServerTransport('/messages', res);
|
||||
transports[transport.sessionId] = transport;
|
||||
res.on("close", () => {
|
||||
delete transports[transport.sessionId];
|
||||
});
|
||||
const server = getServer();
|
||||
await server.connect(transport);
|
||||
});
|
||||
app.post("/messages", async (req, res) => {
|
||||
const sessionId = req.query.sessionId;
|
||||
let transport;
|
||||
const existingTransport = transports[sessionId];
|
||||
if (existingTransport instanceof sse_js_1.SSEServerTransport) {
|
||||
// Reuse existing transport
|
||||
transport = existingTransport;
|
||||
}
|
||||
else {
|
||||
// Transport exists but is not a SSEServerTransport (could be StreamableHTTPServerTransport)
|
||||
res.status(400).json({
|
||||
jsonrpc: '2.0',
|
||||
error: {
|
||||
code: -32000,
|
||||
message: 'Bad Request: Session exists but uses a different transport protocol',
|
||||
},
|
||||
id: null,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (transport) {
|
||||
await transport.handlePostMessage(req, res, req.body);
|
||||
}
|
||||
else {
|
||||
res.status(400).send('No transport found for sessionId');
|
||||
}
|
||||
});
|
||||
// Start the server
|
||||
const PORT = 3000;
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Backwards compatible MCP server listening on port ${PORT}`);
|
||||
console.log(`
|
||||
==============================================
|
||||
SUPPORTED TRANSPORT OPTIONS:
|
||||
|
||||
1. Streamable Http(Protocol version: 2025-03-26)
|
||||
Endpoint: /mcp
|
||||
Methods: GET, POST, DELETE
|
||||
Usage:
|
||||
- Initialize with POST to /mcp
|
||||
- Establish SSE stream with GET to /mcp
|
||||
- Send requests with POST to /mcp
|
||||
- Terminate session with DELETE to /mcp
|
||||
|
||||
2. Http + SSE (Protocol version: 2024-11-05)
|
||||
Endpoints: /sse (GET) and /messages (POST)
|
||||
Usage:
|
||||
- Establish SSE stream with GET to /sse
|
||||
- Send requests with POST to /messages?sessionId=<id>
|
||||
==============================================
|
||||
`);
|
||||
});
|
||||
// Handle server shutdown
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Shutting down server...');
|
||||
// Close all active transports to properly clean up resources
|
||||
for (const sessionId in transports) {
|
||||
try {
|
||||
console.log(`Closing transport for session ${sessionId}`);
|
||||
await transports[sessionId].close();
|
||||
delete transports[sessionId];
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`Error closing transport for session ${sessionId}:`, error);
|
||||
}
|
||||
}
|
||||
console.log('Server shutdown complete');
|
||||
process.exit(0);
|
||||
});
|
||||
//# sourceMappingURL=sseAndStreamableHttpCompatibleServer.js.map
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user