#
tokens: 39134/50000 6/128 files (page 3/9)
lines: off (toggle) GitHub
raw markdown copy
This is page 3 of 9. Use http://codebase.md/tejpalvirk/contextmanager?lines=false&page={x} to view the full context.

# Directory Structure

```
├── .gitattributes
├── .gitignore
├── build-all-domains.sh
├── developer
│   ├── .gitattributes
│   ├── developer_advancedcontext.txt
│   ├── developer_buildcontext.txt
│   ├── developer_deletecontext.txt
│   ├── developer_endsession_examples.txt
│   ├── developer_endsession.txt
│   ├── developer_loadcontext.txt
│   ├── developer_startsession.txt
│   ├── Dockerfile
│   ├── index.d.ts
│   ├── index.js
│   ├── index.ts
│   ├── package.json
│   ├── README.md
│   └── tsconfig.json
├── dist
│   ├── developer
│   │   ├── index.d.ts
│   │   └── index.js
│   ├── main
│   │   ├── descriptions
│   │   │   ├── common_advancedcontext.txt
│   │   │   ├── common_buildcontext.txt
│   │   │   ├── common_deletecontext.txt
│   │   │   ├── common_endsession.txt
│   │   │   ├── common_loadcontext.txt
│   │   │   ├── common_startsession.txt
│   │   │   ├── developer_advancedcontext.txt
│   │   │   ├── developer_buildcontext.txt
│   │   │   ├── developer_deletecontext.txt
│   │   │   ├── developer_endsession_examples.txt
│   │   │   ├── developer_endsession.txt
│   │   │   ├── developer_loadcontext.txt
│   │   │   ├── developer_startsession.txt
│   │   │   ├── project_advancedcontext.txt
│   │   │   ├── project_buildcontext.txt
│   │   │   ├── project_deletecontext.txt
│   │   │   ├── project_endsession_examples.txt
│   │   │   ├── project_endsession.txt
│   │   │   ├── project_loadcontext.txt
│   │   │   ├── project_startsession.txt
│   │   │   ├── qualitativeresearch_advancedcontext.txt
│   │   │   ├── qualitativeresearch_buildcontext.txt
│   │   │   ├── qualitativeresearch_deletecontext.txt
│   │   │   ├── qualitativeresearch_endsession_examples.txt
│   │   │   ├── qualitativeresearch_endsession.txt
│   │   │   ├── qualitativeresearch_loadcontext.txt
│   │   │   ├── qualitativeresearch_startsession.txt
│   │   │   ├── quantitativeresearch_advancedcontext.txt
│   │   │   ├── quantitativeresearch_buildcontext.txt
│   │   │   ├── quantitativeresearch_deletecontext.txt
│   │   │   ├── quantitativeresearch_endsession_examples.txt
│   │   │   ├── quantitativeresearch_endsession.txt
│   │   │   ├── quantitativeresearch_loadcontext.txt
│   │   │   ├── quantitativeresearch_startsession.txt
│   │   │   ├── student_advancedcontext.txt
│   │   │   ├── student_buildcontext.txt
│   │   │   ├── student_deletecontext.txt
│   │   │   ├── student_endsession_examples.txt
│   │   │   ├── student_endsession.txt
│   │   │   ├── student_loadcontext.txt
│   │   │   └── student_startsession.txt
│   │   ├── index.d.ts
│   │   ├── index.js
│   │   ├── mcp.d.ts
│   │   └── mcp.js
│   ├── project
│   │   ├── index.d.ts
│   │   └── index.js
│   ├── qualitativeresearch
│   │   ├── index.d.ts
│   │   └── index.js
│   ├── quantitativeresearch
│   │   ├── index.d.ts
│   │   └── index.js
│   └── student
│       ├── index.d.ts
│       └── index.js
├── main
│   ├── descriptions
│   │   ├── common_advancedcontext.txt
│   │   ├── common_buildcontext.txt
│   │   ├── common_deletecontext.txt
│   │   ├── common_endsession.txt
│   │   ├── common_loadcontext.txt
│   │   ├── common_startsession.txt
│   │   ├── developer_advancedcontext.txt
│   │   ├── developer_buildcontext.txt
│   │   ├── developer_deletecontext.txt
│   │   ├── developer_endsession_examples.txt
│   │   ├── developer_endsession.txt
│   │   ├── developer_loadcontext.txt
│   │   ├── developer_startsession.txt
│   │   ├── project_advancedcontext.txt
│   │   ├── project_buildcontext.txt
│   │   ├── project_deletecontext.txt
│   │   ├── project_endsession_examples.txt
│   │   ├── project_endsession.txt
│   │   ├── project_loadcontext.txt
│   │   ├── project_startsession.txt
│   │   ├── qualitativeresearch_advancedcontext.txt
│   │   ├── qualitativeresearch_buildcontext.txt
│   │   ├── qualitativeresearch_deletecontext.txt
│   │   ├── qualitativeresearch_endsession_examples.txt
│   │   ├── qualitativeresearch_endsession.txt
│   │   ├── qualitativeresearch_loadcontext.txt
│   │   ├── qualitativeresearch_startsession.txt
│   │   ├── quantitativeresearch_advancedcontext.txt
│   │   ├── quantitativeresearch_buildcontext.txt
│   │   ├── quantitativeresearch_deletecontext.txt
│   │   ├── quantitativeresearch_endsession_examples.txt
│   │   ├── quantitativeresearch_endsession.txt
│   │   ├── quantitativeresearch_loadcontext.txt
│   │   ├── quantitativeresearch_startsession.txt
│   │   ├── student_advancedcontext.txt
│   │   ├── student_buildcontext.txt
│   │   ├── student_deletecontext.txt
│   │   ├── student_endsession_examples.txt
│   │   ├── student_endsession.txt
│   │   ├── student_loadcontext.txt
│   │   └── student_startsession.txt
│   ├── index.js
│   ├── index.ts
│   ├── mcp.ts
│   ├── package.json
│   ├── README.md
│   └── tsconfig.json
├── package-lock.json
├── package.json
├── project
│   ├── .gitattributes
│   ├── Dockerfile
│   ├── index.d.ts
│   ├── index.js
│   ├── index.ts
│   ├── package.json
│   ├── project_advancedcontext.txt
│   ├── project_buildcontext.txt
│   ├── project_deletecontext.txt
│   ├── project_endsession_examples.txt
│   ├── project_endsession.txt
│   ├── project_loadcontext.txt
│   ├── project_startsession.txt
│   ├── README.md
│   └── tsconfig.json
├── qualitativeresearch
│   ├── .gitattributes
│   ├── Dockerfile
│   ├── index.d.ts
│   ├── index.js
│   ├── index.ts
│   ├── package.json
│   ├── qualitativeresearch_advancedcontext.txt
│   ├── qualitativeresearch_buildcontext.txt
│   ├── qualitativeresearch_deletecontext.txt
│   ├── qualitativeresearch_endsession_examples.txt
│   ├── qualitativeresearch_endsession.txt
│   ├── qualitativeresearch_loadcontext.txt
│   ├── qualitativeresearch_startsession.txt
│   ├── README.md
│   └── tsconfig.json
├── quantitativeresearch
│   ├── .gitattributes
│   ├── Dockerfile
│   ├── index.d.ts
│   ├── index.js
│   ├── index.ts
│   ├── package.json
│   ├── quantitativeresearch_advancedcontext.txt
│   ├── quantitativeresearch_buildcontext.txt
│   ├── quantitativeresearch_deletecontext.txt
│   ├── quantitativeresearch_endsession_examples.txt
│   ├── quantitativeresearch_endsession.txt
│   ├── quantitativeresearch_loadcontext.txt
│   ├── quantitativeresearch_startsession.txt
│   ├── README.md
│   └── tsconfig.json
├── README.md
├── student
│   ├── .gitattributes
│   ├── Dockerfile
│   ├── index.d.ts
│   ├── index.js
│   ├── index.ts
│   ├── package.json
│   ├── README.md
│   ├── student_advancedcontext.txt
│   ├── student_buildcontext.txt
│   ├── student_deletecontext.txt
│   ├── student_endsession_examples.txt
│   ├── student_endsession.txt
│   ├── student_loadcontext.txt
│   ├── student_startsession.txt
│   └── tsconfig.json
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/main/descriptions/quantitativeresearch_endsession.txt:
--------------------------------------------------------------------------------

```
A multi-stage tool for documenting quantitative research sessions, recording statistical analyses, tracking dataset updates, and creating a structured record of research evolution.

When to use this tool:
- Concluding a quantitative research analysis session
- Documenting updates to datasets and variables
- Recording new statistical analyses and test results
- Tracking creation of data visualizations
- Documenting hypothesis test results and conclusions
- Updating statistical model performance information
- Creating a structured record of research activities
- Establishing a formal conclusion to a focused research period
- Building a historical record of project development
- Documenting observations and insights from statistical analysis
- Updating status values for research activities and entities
- Assigning or modifying priority levels for research tasks
- Establishing or modifying sequential relationships between research processes

Key features:
- Provides a structured, multi-stage workflow for research session documentation
- Records dataset updates in the knowledge graph
- Captures new statistical analyses and their results
- Tracks creation of data visualizations and their purposes
- Documents hypothesis test outcomes with statistical significance
- Updates statistical model performance metrics
- Updates project status information
- Maintains session continuity with unique session IDs
- Supports revision of previous stages when needed
- Offers a comprehensive assembly stage that consolidates all session information
- Manages status progression of research activities
- Tracks priority assignments for research tasks
- Documents sequential relationships between research processes

The endsession tool uses a sequential, multi-stage approach with 9 typical stages:
1. Summary Stage: Records basic session information
2. Dataset Updates Stage: Documents changes to datasets
3. New Analyses Stage: Records new statistical tests performed
4. New Visualizations Stage: Documents visualizations created
5. Hypothesis Results Stage: Records outcomes of hypothesis tests
6. Model Updates Stage: Documents changes to statistical models
7. Status Updates Stage: Records changes to entity status values
8. Project Status Stage: Updates the overall project status
9. Assembly Stage: Consolidates all information and finalizes the session record

Parameters explained:
1. sessionId: Required - Unique identifier for the research session
  - Obtained from the startsession tool
  - Example: "quant_1234567890_abc123"
2. stage: Required - Current stage of the endsession workflow
  - Accepts: "summary", "datasetUpdates", "newAnalyses", "newVisualizations", "hypothesisResults", "modelUpdates", "statusUpdates", "projectStatus", or "assembly"
  - Each stage has specific data requirements and processing logic
3. stageNumber: Required - The sequence number of the current stage
  - Starts at 1 and typically progresses through the stages
  - Used to track progress through the session documentation workflow
4. totalStages: Required - Total number of stages planned for this workflow
  - Typically 9 for the complete workflow
  - Provides context for the progress within the overall process
5. analysis: Optional - Text analysis or observations for the current stage
  - Descriptive text explaining the work done in this stage
  - Example: "Analyzed multiple regression results and identified significant predictors"
6. stageData: Optional - Stage-specific structured data
  - Structure varies by stage type:
    * summary: { summary: "Session summary text", duration: "3 hours", project: "ProjectName" }
    * datasetUpdates: { datasets: [{ name: "Dataset1", size: "500 rows", variables: "10", status: "active", description: "Dataset description" }] }
    * newAnalyses: { analyses: [{ name: "Analysis1", type: "regression", result: "p<0.05", pValue: "0.03", variables: ["var1", "var2"] }] }
    * newVisualizations: { visualizations: [{ name: "Viz1", type: "scatter", description: "Correlation visualization", datasetName: "Dataset1" }] }
    * hypothesisResults: { hypotheses: [{ name: "H1", status: "completed", evidence: "Statistical significance in regression model", pValue: "0.02" }] }
    * modelUpdates: { models: [{ name: "Model1", type: "regression", performance: "R²=0.85", variables: ["var1", "var2"] }] }
    * statusUpdates: { statusUpdates: [{ entityName: "Dataset1", newStatus: "completed", note: "Data cleaning and validation complete" }, { entityName: "Model2", newStatus: "active", note: "Model training in progress" }] }
    * projectStatus: { projectStatus: "active", projectObservation: "Data analysis phase complete", priorityUpdates: [{ entityName: "AnalysisTask1", priority: "high", note: "Critical for upcoming publication" }], sequenceUpdates: [{ before: "DataCleaning", after: "ModelTraining", note: "Reorganized analysis workflow" }] }
    * assembly: No stageData needed - automatically assembled from previous stages
7. nextStageNeeded: Required - Whether additional stages are needed after this one
  - Boolean value (true/false)
  - Set to false on the final stage to complete the session
8. isRevision: Optional - Whether this is revising a previous stage
  - Boolean value (true/false)
  - Default: false
9. revisesStage: Optional - If revising, which stage number is being revised
  - Required when isRevision is true
  - Indicates which previous stage is being updated

Status and Priority Management:
- The statusUpdates stage allows for batch updates to entity status values
- Valid status values include: active, completed, pending, abandoned
- Priority assignments (high, low) can be modified in the projectStatus stage
- Status changes are implemented through has_status relations
- Priority changes are implemented through has_priority relations
- Status and priority changes are tracked to maintain research progress history

Sequential Process Management:
- The projectStatus stage allows for defining or modifying sequential relationships
- The precedes relation is used to establish logical ordering between research processes
- Sequential updates help maintain a coherent research workflow
- Process sequences can be visualized through the loadcontext tool
- Critical research sequences are maintained to ensure methodological integrity

When the endsession workflow completes (assembly stage with nextStageNeeded: false), the tool performs these updates:
1. Dataset Entities: Updates existing datasets or creates new dataset entities with the provided information
2. Statistical Analyses: Creates entities for statistical tests and links them to projects and variables
3. Visualizations: Creates entities for data visualizations and links them to datasets and projects
4. Hypothesis Updates: Updates existing hypotheses or creates new hypothesis entities with test results
5. Model Updates: Updates existing model entities or creates new models with performance metrics
6. Status Updates: Updates entity status values through has_status relations 
7. Priority Updates: Updates entity priority values through has_priority relations
8. Sequence Updates: Updates sequential relationships through precedes relations
9. Project Status: Updates the project status, adds an updated timestamp, and records observations

Return information:
- JSON response with the following structure when stages are in progress:
  * success: Boolean indicating whether the operation succeeded
  * stageCompleted: The stage that was just completed
  * nextStageNeeded: Whether more stages are required
  * stageResult: The processed result of the current stage
- Formatted markdown text summary when the session is completed, including:
  * Session date and project name
  * Summary of the session
  * Dataset updates
  * New statistical analyses
  * New visualizations
  * Hypothesis test results
  * Model updates
  * Status changes
  * Priority modifications
  * Sequential relationship updates
  * Project status update

You should:
- Complete all stages in order for comprehensive session documentation
- Provide specific details in each stage for accurate research documentation
- Specify dataset updates with clear size, variable count, and status information
- Include p-values and variable names for statistical analyses
- Connect visualizations to specific datasets when possible
- Document hypothesis test results with evidence and significance levels
- Include performance metrics when updating statistical models
- Update entity status using has_status relations with valid status values (active, completed, pending, abandoned)
- Assign priorities using has_priority relations with valid priority values (high, low)
- Define process sequences using precedes relations to establish research workflows
- Include relevant observations for project status updates
- If making a revision, specify which stage is being revised
- Only mark nextStageNeeded as false on the final assembly stage
- Review the final summary message to confirm all session details were recorded properly
- Use the unique session ID consistently across all stages 
```

--------------------------------------------------------------------------------
/quantitativeresearch/quantitativeresearch_endsession.txt:
--------------------------------------------------------------------------------

```
A multi-stage tool for documenting quantitative research sessions, recording statistical analyses, tracking dataset updates, and creating a structured record of research evolution.

When to use this tool:
- Concluding a quantitative research analysis session
- Documenting updates to datasets and variables
- Recording new statistical analyses and test results
- Tracking creation of data visualizations
- Documenting hypothesis test results and conclusions
- Updating statistical model performance information
- Creating a structured record of research activities
- Establishing a formal conclusion to a focused research period
- Building a historical record of project development
- Documenting observations and insights from statistical analysis
- Updating status values for research activities and entities
- Assigning or modifying priority levels for research tasks
- Establishing or modifying sequential relationships between research processes

Key features:
- Provides a structured, multi-stage workflow for research session documentation
- Records dataset updates in the knowledge graph
- Captures new statistical analyses and their results
- Tracks creation of data visualizations and their purposes
- Documents hypothesis test outcomes with statistical significance
- Updates statistical model performance metrics
- Updates project status information
- Maintains session continuity with unique session IDs
- Supports revision of previous stages when needed
- Offers a comprehensive assembly stage that consolidates all session information
- Manages status progression of research activities
- Tracks priority assignments for research tasks
- Documents sequential relationships between research processes

The endsession tool uses a sequential, multi-stage approach with 9 typical stages:
1. Summary Stage: Records basic session information
2. Dataset Updates Stage: Documents changes to datasets
3. New Analyses Stage: Records new statistical tests performed
4. New Visualizations Stage: Documents visualizations created
5. Hypothesis Results Stage: Records outcomes of hypothesis tests
6. Model Updates Stage: Documents changes to statistical models
7. Status Updates Stage: Records changes to entity status values
8. Project Status Stage: Updates the overall project status
9. Assembly Stage: Consolidates all information and finalizes the session record

Parameters explained:
1. sessionId: Required - Unique identifier for the research session
  - Obtained from the startsession tool
  - Example: "quant_1234567890_abc123"
2. stage: Required - Current stage of the endsession workflow
  - Accepts: "summary", "datasetUpdates", "newAnalyses", "newVisualizations", "hypothesisResults", "modelUpdates", "statusUpdates", "projectStatus", or "assembly"
  - Each stage has specific data requirements and processing logic
3. stageNumber: Required - The sequence number of the current stage
  - Starts at 1 and typically progresses through the stages
  - Used to track progress through the session documentation workflow
4. totalStages: Required - Total number of stages planned for this workflow
  - Typically 9 for the complete workflow
  - Provides context for the progress within the overall process
5. analysis: Optional - Text analysis or observations for the current stage
  - Descriptive text explaining the work done in this stage
  - Example: "Analyzed multiple regression results and identified significant predictors"
6. stageData: Optional - Stage-specific structured data
  - Structure varies by stage type:
    * summary: { summary: "Session summary text", duration: "3 hours", project: "ProjectName" }
    * datasetUpdates: { datasets: [{ name: "Dataset1", size: "500 rows", variables: "10", status: "active", description: "Dataset description" }] }
    * newAnalyses: { analyses: [{ name: "Analysis1", type: "regression", result: "p<0.05", pValue: "0.03", variables: ["var1", "var2"] }] }
    * newVisualizations: { visualizations: [{ name: "Viz1", type: "scatter", description: "Correlation visualization", datasetName: "Dataset1" }] }
    * hypothesisResults: { hypotheses: [{ name: "H1", status: "completed", evidence: "Statistical significance in regression model", pValue: "0.02" }] }
    * modelUpdates: { models: [{ name: "Model1", type: "regression", performance: "R²=0.85", variables: ["var1", "var2"] }] }
    * statusUpdates: { statusUpdates: [{ entityName: "Dataset1", newStatus: "completed", note: "Data cleaning and validation complete" }, { entityName: "Model2", newStatus: "active", note: "Model training in progress" }] }
    * projectStatus: { projectStatus: "active", projectObservation: "Data analysis phase complete", priorityUpdates: [{ entityName: "AnalysisTask1", priority: "high", note: "Critical for upcoming publication" }], sequenceUpdates: [{ before: "DataCleaning", after: "ModelTraining", note: "Reorganized analysis workflow" }] }
    * assembly: No stageData needed - automatically assembled from previous stages
7. nextStageNeeded: Required - Whether additional stages are needed after this one
  - Boolean value (true/false)
  - Set to false on the final stage to complete the session
8. isRevision: Optional - Whether this is revising a previous stage
  - Boolean value (true/false)
  - Default: false
9. revisesStage: Optional - If revising, which stage number is being revised
  - Required when isRevision is true
  - Indicates which previous stage is being updated

Status and Priority Management:
- The statusUpdates stage allows for batch updates to entity status values
- Valid status values include: active, completed, pending, abandoned
- Priority assignments (high, low) can be modified in the projectStatus stage
- Status changes are implemented through has_status relations
- Priority changes are implemented through has_priority relations
- Status and priority changes are tracked to maintain research progress history

Sequential Process Management:
- The projectStatus stage allows for defining or modifying sequential relationships
- The precedes relation is used to establish logical ordering between research processes
- Sequential updates help maintain a coherent research workflow
- Process sequences can be visualized through the loadcontext tool
- Critical research sequences are maintained to ensure methodological integrity

When the endsession workflow completes (assembly stage with nextStageNeeded: false), the tool performs these updates:
1. Dataset Entities: Updates existing datasets or creates new dataset entities with the provided information
2. Statistical Analyses: Creates entities for statistical tests and links them to projects and variables
3. Visualizations: Creates entities for data visualizations and links them to datasets and projects
4. Hypothesis Updates: Updates existing hypotheses or creates new hypothesis entities with test results
5. Model Updates: Updates existing model entities or creates new models with performance metrics
6. Status Updates: Updates entity status values through has_status relations 
7. Priority Updates: Updates entity priority values through has_priority relations
8. Sequence Updates: Updates sequential relationships through precedes relations
9. Project Status: Updates the project status, adds an updated timestamp, and records observations

Return information:
- JSON response with the following structure when stages are in progress:
  * success: Boolean indicating whether the operation succeeded
  * stageCompleted: The stage that was just completed
  * nextStageNeeded: Whether more stages are required
  * stageResult: The processed result of the current stage
- Formatted markdown text summary when the session is completed, including:
  * Session date and project name
  * Summary of the session
  * Dataset updates
  * New statistical analyses
  * New visualizations
  * Hypothesis test results
  * Model updates
  * Status changes
  * Priority modifications
  * Sequential relationship updates
  * Project status update

You should:
- Complete all stages in order for comprehensive session documentation
- Provide specific details in each stage for accurate research documentation
- Specify dataset updates with clear size, variable count, and status information
- Include p-values and variable names for statistical analyses
- Connect visualizations to specific datasets when possible
- Document hypothesis test results with evidence and significance levels
- Include performance metrics when updating statistical models
- Update entity status using has_status relations with valid status values (active, completed, pending, abandoned)
- Assign priorities using has_priority relations with valid priority values (high, low)
- Define process sequences using precedes relations to establish research workflows
- Include relevant observations for project status updates
- If making a revision, specify which stage is being revised
- Only mark nextStageNeeded as false on the final assembly stage
- Review the final summary message to confirm all session details were recorded properly
- Use the unique session ID consistently across all stages 
```

--------------------------------------------------------------------------------
/main/index.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { z } from "zod";
import path from "path";
import { fileURLToPath } from "url";
// Get the directory where the contextmanager is located
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Domain client class
class DomainClient {
    constructor(domain) {
        this.domain = domain;
        this.client = null;
        this.transport = null;
        this.connected = false;
        this.process = null;
        this.name = domain.name;
    }
    async connect() {
        if (this.connected) {
            return true;
        }
        try {
            // Create client
            this.client = new Client({
                name: `contextmanager-${this.name}-client`,
                version: "1.0.0"
            }, {
                capabilities: {
                    resources: {},
                    tools: {},
                    prompts: {}
                }
            });
            // Connect to domain server
            if (this.domain.host && this.domain.port) {
                // Connect via SSE
                const url = new URL(`http://${this.domain.host}:${this.domain.port}${this.domain.path || '/sse'}`);
                this.transport = new SSEClientTransport(url);
            }
            else if (this.domain.command) {
                // Connect via stdio
                this.transport = new StdioClientTransport({
                    command: this.domain.command,
                    args: this.domain.args || [],
                });
            }
            else {
                console.error(`Domain ${this.name} has no connection information`);
                return false;
            }
            await this.client.connect(this.transport);
            this.connected = true;
            return true;
        }
        catch (error) {
            console.error(`Failed to connect to domain ${this.name}:`, error);
            this.connected = false;
            return false;
        }
    }
    async disconnect() {
        if (!this.connected) {
            return;
        }
        try {
            if (this.client) {
                // Manually close the transport as there's no official disconnect method
                if (this.transport) {
                    if ('close' in this.transport) {
                        await this.transport.close();
                    }
                }
            }
            this.connected = false;
        }
        catch (error) {
            console.error(`Error disconnecting from domain ${this.name}:`, error);
        }
    }
    async callTool(toolRequest) {
        if (!this.connected || !this.client) {
            const connected = await this.connect();
            if (!connected) {
                return {
                    content: [{ type: "text", text: `Error: Not connected to domain ${this.name}` }],
                    isError: true
                };
            }
        }
        try {
            if (!this.client) {
                throw new Error(`Client for domain ${this.name} is not initialized`);
            }
            const result = await this.client.callTool(toolRequest);
            return result;
        }
        catch (error) {
            console.error(`Error calling tool ${toolRequest.name} on domain ${this.name}:`, error);
            return {
                content: [{ type: "text", text: `Error calling tool ${toolRequest.name} on domain ${this.name}: ${error}` }],
                isError: true
            };
        }
    }
    async readResource(resourceRequest) {
        if (!this.connected || !this.client) {
            const connected = await this.connect();
            if (!connected) {
                return {
                    contents: [{
                            uri: resourceRequest.uri,
                            text: `Error: Not connected to domain ${this.name}`
                        }]
                };
            }
        }
        try {
            if (!this.client) {
                throw new Error(`Client for domain ${this.name} is not initialized`);
            }
            return await this.client.readResource(resourceRequest);
        }
        catch (error) {
            console.error(`Error reading resource ${resourceRequest.uri} from domain ${this.name}:`, error);
            return {
                contents: [{
                        uri: resourceRequest.uri,
                        text: `Error reading resource: ${error}`
                    }]
            };
        }
    }
}
// In-memory storage
const domains = [
    {
        name: "developer",
        description: "Software development context with entities like projects, components, and tasks",
        entityTypes: ["project", "component", "task", "issue", "commit"],
        command: "node",
        args: [path.resolve(__dirname, "../developer/index.js")]
    },
    {
        name: "project",
        description: "Project management context with entities like projects, tasks, and resources",
        entityTypes: ["project", "task", "resource", "milestone", "risk"],
        command: "node",
        args: [path.resolve(__dirname, "../project/index.js")]
    },
    {
        name: "student",
        description: "Educational context with entities like courses, assignments, and exams",
        entityTypes: ["course", "assignment", "exam", "note", "grade"],
        command: "node",
        args: [path.resolve(__dirname, "../student/index.js")]
    },
    {
        name: "qualitativeresearch",
        description: "Qualitative research context with entities like studies, participants, and interviews",
        entityTypes: ["study", "participant", "interview", "code", "theme"],
        command: "node",
        args: [path.resolve(__dirname, "../qualitativeresearch/index.js")]
    },
    {
        name: "quantitativeresearch",
        description: "Quantitative research context with entities like datasets, variables, and analyses",
        entityTypes: ["dataset", "variable", "analysis", "model", "result"],
        command: "node",
        args: [path.resolve(__dirname, "../quantitativeresearch/index.js")]
    }
];
// Domain clients
const domainClients = {};
// Initialize domain clients
for (const domain of domains) {
    domainClients[domain.name] = new DomainClient(domain);
}
// In-memory flow management
const flows = [];
let activeDomain = null;
let flowCounter = 0;
// Create an MCP server
const server = new McpServer({
    name: "Context Manager",
    version: "1.0.0"
});
// Domain management tools
server.tool("setActiveDomain", { domain: z.string() }, async ({ domain }) => {
    const foundDomain = domains.find(d => d.name.toLowerCase() === domain.toLowerCase());
    if (!foundDomain) {
        return {
            content: [{ type: "text", text: `Error: Domain '${domain}' not found. Available domains: ${domains.map(d => d.name).join(", ")}` }],
            isError: true
        };
    }
    // Connect to the domain server
    const domainClient = domainClients[foundDomain.name];
    const connected = await domainClient.connect();
    if (!connected) {
        return {
            content: [{ type: "text", text: `Error: Could not connect to domain server for '${domain}'` }],
            isError: true
        };
    }
    activeDomain = foundDomain.name;
    return {
        content: [{ type: "text", text: `Active domain set to: ${activeDomain}` }]
    };
});
// Flow management tools
server.tool("startsession", {
    domain: z.string()
}, async ({ domain }) => {
    const foundDomain = domains.find(d => d.name.toLowerCase() === domain.toLowerCase());
    if (!foundDomain) {
        return {
            content: [{ type: "text", text: `Error: Domain '${domain}' not found. Available domains: ${domains.map(d => d.name).join(", ")}` }],
            isError: true
        };
    }
    // Connect to the domain server
    const domainClient = domainClients[foundDomain.name];
    const connected = await domainClient.connect();
    if (!connected) {
        return {
            content: [{ type: "text", text: `Error: Could not connect to domain server for '${domain}'` }],
            isError: true
        };
    }
    activeDomain = foundDomain.name;
    flowCounter++;
    // Forward the startsession call to the domain server with a domain-specific session identifier
    try {
        const result = await domainClient.callTool({
            name: "startsession",
            arguments: {}
        });
        const lastWord = result.content[0].text.split(' ').pop();
        // Create a contextmanager flow ID from domain session ID (last word)
        const flowId = `flow_${lastWord}`;
        flows.push({
            id: flowId,
            domain: activeDomain,
            active: true,
            createdAt: Date.now()
        });
        return {
            content: [
                { type: "text", text: `${result.content[0].text}` }
            ],
        };
    }
    catch (error) {
        console.error(`Error starting session for domain ${activeDomain}:`, error);
        return {
            content: [{ type: "text", text: `Error starting session for domain ${activeDomain}: ${error}` }],
            isError: true
        };
    }
});
server.tool("endsession", {
    sessionId: z.string(),
    stage: z.string(),
    stageNumber: z.number(),
    totalStages: z.number(),
    nextStageNeeded: z.boolean(),
    analysis: z.string().optional(),
    isRevision: z.boolean().optional(),
    revisesStage: z.number().optional(),
    stageData: z.any().optional()
}, async ({ sessionId, stage, stageNumber, totalStages, nextStageNeeded, analysis, isRevision, revisesStage, stageData }) => {
    const flowId = `flow_${sessionId}`;
    const flowIndex = flows.findIndex(s => s.id === flowId);
    if (flowIndex === -1) {
        return {
            content: [{ type: "text", text: `Error: Context Manager flow with ID '${flowId}' not found.` }],
            isError: true
        };
    }
    const flow = flows[flowIndex];
    const domainName = flow.domain;
    const domainClient = domainClients[domainName];
    if (!domainClient || !domainClient.connected) {
        const connected = await domainClient.connect();
        if (!connected) {
            return {
                content: [{ type: "text", text: `Error: Could not connect to domain server for '${domainName}'` }],
                isError: true
            };
        }
    }
    // Forward the endsession call to the domain server
    try {
        const result = await domainClient.callTool({
            name: "endsession",
            arguments: {
                sessionId: sessionId,
                stage,
                stageNumber,
                totalStages,
                nextStageNeeded,
                analysis,
                isRevision,
                revisesStage,
                stageData
            }
        });
        if (!nextStageNeeded) {
            flows[flowIndex].active = false;
            return {
                content: [{ type: "text", text: `${result.content[0].text}` }]
            };
        }
        return {
            content: [{ type: "text", text: `${result.content[0].text}` }]
        };
    }
    catch (error) {
        console.error(`Error ending session for domain ${domainName}:`, error);
        return {
            content: [{ type: "text", text: `Error ending session for domain ${domainName}: ${error}` }],
            isError: true
        };
    }
});
// Context management tools
server.tool("buildcontext", {
    type: z.enum(["entities", "relations", "observations"]),
    data: z.any().optional()
}, async ({ type, data }) => {
    if (!activeDomain) {
        return {
            content: [{ type: "text", text: "Error: No active domain set. Use setActiveDomain tool first." }],
            isError: true
        };
    }
    const domainClient = domainClients[activeDomain];
    if (!domainClient || !domainClient.connected) {
        const connected = await domainClient.connect();
        if (!connected) {
            return {
                content: [{ type: "text", text: `Error: Could not connect to domain server for '${activeDomain}'` }],
                isError: true
            };
        }
    }
    // Forward the buildcontext call to the domain server
    try {
        const result = await domainClient.callTool({
            name: "buildcontext",
            arguments: {
                type,
                data
            }
        });
        return result;
    }
    catch (error) {
        console.error(`Error building context for domain ${activeDomain}:`, error);
        return {
            content: [{ type: "text", text: `Error building context for domain ${activeDomain}: ${error}` }],
            isError: true
        };
    }
});
server.tool("deletecontext", {
    type: z.enum(["entities", "relations", "observations"]),
    data: z.any().optional()
}, async ({ type, data }) => {
    if (!activeDomain) {
        return {
            content: [{ type: "text", text: "Error: No active domain set. Use setActiveDomain tool first." }],
            isError: true
        };
    }
    const domainClient = domainClients[activeDomain];
    if (!domainClient || !domainClient.connected) {
        const connected = await domainClient.connect();
        if (!connected) {
            return {
                content: [{ type: "text", text: `Error: Could not connect to domain server for '${activeDomain}'` }],
                isError: true
            };
        }
    }
    // Forward the deletecontext call to the domain server
    try {
        const result = await domainClient.callTool({
            name: "deletecontext",
            arguments: {
                type,
                data
            }
        });
        return result;
    }
    catch (error) {
        console.error(`Error deleting context for domain ${activeDomain}:`, error);
        return {
            content: [{ type: "text", text: `Error deleting context for domain ${activeDomain}: ${error}` }],
            isError: true
        };
    }
});
server.tool("loadcontext", {
    entityName: z.string(),
    entityType: z.string().optional(),
    sessionId: z.string().optional()
}, async ({ entityName, entityType, sessionId }) => {
    if (!activeDomain) {
        return {
            content: [{ type: "text", text: "Error: No active domain set. Use setActiveDomain tool first." }],
            isError: true
        };
    }
    const flowId = `flow_${sessionId}`;
    // Find active contextmanager flow or use provided sessionId
    let targetFlow;
    if (sessionId) {
        targetFlow = flows.find(s => s.id === flowId);
    }
    else {
        targetFlow = flows.find(s => s.domain === activeDomain && s.active);
    }
    if (!targetFlow) {
        return {
            content: [{ type: "text", text: "Error: No active Context Manager flow found. Start a flow first." }],
            isError: true
        };
    }
    const domainClient = domainClients[activeDomain];
    if (!domainClient || !domainClient.connected) {
        const connected = await domainClient.connect();
        if (!connected) {
            return {
                content: [{ type: "text", text: `Error: Could not connect to domain server for '${activeDomain}'` }],
                isError: true
            };
        }
    }
    // Update contextmanager flow with entity details
    targetFlow.entityName = entityName;
    targetFlow.entityType = entityType || "unknown";
    // Forward the loadcontext call to the domain server
    try {
        const result = await domainClient.callTool({
            name: "loadcontext",
            arguments: {
                entityName,
                entityType,
                sessionId: sessionId
            }
        });
        return {
            content: [{
                    type: "text",
                    text: `${result.content[0].text}`
                }]
        };
    }
    catch (error) {
        console.error(`Error loading context for domain ${activeDomain}:`, error);
        return {
            content: [{ type: "text", text: `Error loading context for domain ${activeDomain}: ${error}` }],
            isError: true
        };
    }
});
server.tool("advancedcontext", {
    type: z.enum(["graph", "search", "nodes", "related", "decisions", "milestone"]),
    params: z.any().optional()
}, async ({ type, params }) => {
    if (!activeDomain) {
        return {
            content: [{ type: "text", text: "Error: No active domain set. Use setActiveDomain tool first." }],
            isError: true
        };
    }
    const domainClient = domainClients[activeDomain];
    if (!domainClient || !domainClient.connected) {
        const connected = await domainClient.connect();
        if (!connected) {
            return {
                content: [{ type: "text", text: `Error: Could not connect to domain server for '${activeDomain}'` }],
                isError: true
            };
        }
    }
    // Forward the advancedcontext call to the domain server
    try {
        const result = await domainClient.callTool({
            name: "advancedcontext",
            arguments: {
                type,
                params
            }
        });
        return result;
    }
    catch (error) {
        console.error(`Error performing advanced context operation for domain ${activeDomain}:`, error);
        return {
            content: [{ type: "text", text: `Error performing advanced context operation for domain ${activeDomain}: ${error}` }],
            isError: true
        };
    }
});
// // List all entities
// server.tool(
//   "listAllEntities",
//   {
//     domain: z.string().optional()
//   },
//   async () => {
//     if (!activeDomain) {
//       return {
//         content: [{ type: "text", text: "Error: No active domain set. Use setActiveDomain tool first." }],
//         isError: true
//       };
//     }
//     const domainClient = domainClients[activeDomain];
//     if (!domainClient || !domainClient.connected) {
//       const connected = await domainClient.connect();
//       if (!connected) {
//         return {
//           content: [{ type: "text", text: `Error: Could not connect to domain server for '${activeDomain}'` }],
//           isError: true
//         };
//       }
//     }
//     // Forward the listAllEntities call to the domain server
//     try {
//       const result = await domainClient.callTool({
//         name: "listAllEntities",
//         arguments: {}
//       });
//       return result;
//     } catch (error) {
//       // If the domain server doesn't support listAllEntities, fall back to our domain registry
//       const domain = domains.find(d => d.name === activeDomain);
//       if (!domain) {
//         return {
//           content: [{ type: "text", text: `Error: Domain '${activeDomain}' not found.` }],
//           isError: true
//         };
//       }
//       return {
//         content: [{ 
//           type: "text", 
//           text: `Available entity types in ${activeDomain} domain: ${domain.entityTypes.join(", ")}` 
//         }]
//       };
//     }
//   }
// );
// Domain discovery resources
server.resource("domains", "domains://list", async (uri) => ({
    contents: [{
            uri: uri.href,
            text: JSON.stringify(domains, null, 2)
        }]
}));
// Cross-domain functionality
server.tool("relateCrossDomain", {
    fromDomain: z.string(),
    fromEntity: z.string(),
    toDomain: z.string(),
    toEntity: z.string(),
    relationType: z.string()
}, async ({ fromDomain, fromEntity, toDomain, toEntity, relationType }) => {
    // Validate domains
    const fromDomainInfo = domains.find(d => d.name.toLowerCase() === fromDomain.toLowerCase());
    const toDomainInfo = domains.find(d => d.name.toLowerCase() === toDomain.toLowerCase());
    if (!fromDomainInfo) {
        return {
            content: [{ type: "text", text: `Error: Source domain '${fromDomain}' not found.` }],
            isError: true
        };
    }
    if (!toDomainInfo) {
        return {
            content: [{ type: "text", text: `Error: Target domain '${toDomain}' not found.` }],
            isError: true
        };
    }
    // Create cross-domain relation by adding observations to both entities
    try {
        // Connect to source domain
        const fromDomainClient = domainClients[fromDomainInfo.name];
        if (!fromDomainClient || !fromDomainClient.connected) {
            const connected = await fromDomainClient.connect();
            if (!connected) {
                return {
                    content: [{ type: "text", text: `Error: Could not connect to domain server for '${fromDomain}'` }],
                    isError: true
                };
            }
        }
        // Connect to target domain
        const toDomainClient = domainClients[toDomainInfo.name];
        if (!toDomainClient || !toDomainClient.connected) {
            const connected = await toDomainClient.connect();
            if (!connected) {
                return {
                    content: [{ type: "text", text: `Error: Could not connect to domain server for '${toDomain}'` }],
                    isError: true
                };
            }
        }
        // Add observation to source entity about relation to target entity
        await fromDomainClient.callTool({
            name: "buildcontext",
            arguments: {
                type: "observations",
                data: {
                    observations: [
                        {
                            entityName: fromEntity,
                            contents: [`Related to ${toEntity} (${toDomainInfo.name} domain) via ${relationType}`]
                        }
                    ]
                }
            }
        });
        // Add observation to target entity about relation from source entity
        await toDomainClient.callTool({
            name: "buildcontext",
            arguments: {
                type: "observations",
                data: {
                    observations: [
                        {
                            entityName: toEntity,
                            contents: [`Related from ${fromEntity} (${fromDomainInfo.name} domain) via ${relationType}`]
                        }
                    ]
                }
            }
        });
        return {
            content: [{
                    type: "text",
                    text: `Created cross-domain relation: ${fromEntity} (${fromDomain}) --[${relationType}]--> ${toEntity} (${toDomain})`
                }]
        };
    }
    catch (error) {
        console.error(`Error creating cross-domain relation:`, error);
        return {
            content: [{ type: "text", text: `Error creating cross-domain relation: ${error}` }],
            isError: true
        };
    }
});
// Main function to start the server
async function main() {
    // Start receiving messages on stdin and sending messages on stdout
    const transport = new StdioServerTransport();
    await server.connect(transport);
}
// Execute the main function
main().catch(error => {
    console.error("Error in contextmanager:", error);
    process.exit(1);
});

```

--------------------------------------------------------------------------------
/main/mcp.ts:
--------------------------------------------------------------------------------

```typescript
import { Server, ServerOptions } from "@modelcontextprotocol/sdk/server/index.js";
import { zodToJsonSchema } from "zod-to-json-schema";
import {
  z,
  ZodRawShape,
  ZodObject,
  ZodString,
  AnyZodObject,
  ZodTypeAny,
  ZodType,
  ZodTypeDef,
  ZodOptional,
} from "zod";
import {
  Implementation,
  Tool,
  ListToolsResult,
  CallToolResult,
  McpError,
  ErrorCode,
  CompleteRequest,
  CompleteResult,
  PromptReference,
  ResourceReference,
  Resource,
  ListResourcesResult,
  ListResourceTemplatesRequestSchema,
  ReadResourceRequestSchema,
  ListToolsRequestSchema,
  CallToolRequestSchema,
  ListResourcesRequestSchema,
  ListPromptsRequestSchema,
  GetPromptRequestSchema,
  CompleteRequestSchema,
  ListPromptsResult,
  Prompt,
  PromptArgument,
  GetPromptResult,
  ReadResourceResult,
} from "@modelcontextprotocol/sdk/types.js";
import { Completable, CompletableDef } from "@modelcontextprotocol/sdk/server/completable.js";
import { UriTemplate, Variables } from "@modelcontextprotocol/sdk/shared/uriTemplate.js";
import { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";

/**
 * High-level MCP server that provides a simpler API for working with resources, tools, and prompts.
 * For advanced usage (like sending notifications or setting custom request handlers), use the underlying
 * Server instance available via the `server` property.
 */
export class McpServer {
  /**
   * The underlying Server instance, useful for advanced operations like sending notifications.
   */
  public readonly server: Server;

  private _registeredResources: { [uri: string]: RegisteredResource } = {};
  private _registeredResourceTemplates: {
    [name: string]: RegisteredResourceTemplate;
  } = {};
  private _registeredTools: { [name: string]: RegisteredTool } = {};
  private _registeredPrompts: { [name: string]: RegisteredPrompt } = {};

  constructor(serverInfo: Implementation, options?: ServerOptions) {
    this.server = new Server(serverInfo, options);
  }

  /**
   * Attaches to the given transport, starts it, and starts listening for messages.
   *
   * The `server` object assumes ownership of the Transport, replacing any callbacks that have already been set, and expects that it is the only user of the Transport instance going forward.
   */
  async connect(transport: Transport): Promise<void> {
    return await this.server.connect(transport);
  }

  /**
   * Closes the connection.
   */
  async close(): Promise<void> {
    await this.server.close();
  }

  private _toolHandlersInitialized = false;

  private setToolRequestHandlers() {
    if (this._toolHandlersInitialized) {
      return;
    }
    
    this.server.assertCanSetRequestHandler(
      ListToolsRequestSchema.shape.method.value,
    );
    this.server.assertCanSetRequestHandler(
      CallToolRequestSchema.shape.method.value,
    );

    this.server.registerCapabilities({
      tools: {},
    });

    this.server.setRequestHandler(
      ListToolsRequestSchema,
      (): ListToolsResult => ({
        tools: Object.entries(this._registeredTools).map(
          ([name, tool]): Tool => {
            return {
              name,
              description: tool.description,
              inputSchema: tool.inputSchema
                ? (zodToJsonSchema(tool.inputSchema, {
                    strictUnions: true,
                  }) as Tool["inputSchema"])
                : EMPTY_OBJECT_JSON_SCHEMA,
            };
          },
        ),
      }),
    );

    this.server.setRequestHandler(
      CallToolRequestSchema,
      async (request, extra): Promise<CallToolResult> => {
        const tool = this._registeredTools[request.params.name];
        if (!tool) {
          throw new McpError(
            ErrorCode.InvalidParams,
            `Tool ${request.params.name} not found`,
          );
        }

        if (tool.inputSchema) {
          const parseResult = await tool.inputSchema.safeParseAsync(
            request.params.arguments,
          );
          if (!parseResult.success) {
            throw new McpError(
              ErrorCode.InvalidParams,
              `Invalid arguments for tool ${request.params.name}: ${parseResult.error.message}`,
            );
          }

          const args = parseResult.data;
          const cb = tool.callback as ToolCallback<ZodRawShape>;
          try {
            return await Promise.resolve(cb(args, extra));
          } catch (error) {
            return {
              content: [
                {
                  type: "text",
                  text: error instanceof Error ? error.message : String(error),
                },
              ],
              isError: true,
            };
          }
        } else {
          const cb = tool.callback as ToolCallback<undefined>;
          try {
            return await Promise.resolve(cb(extra));
          } catch (error) {
            return {
              content: [
                {
                  type: "text",
                  text: error instanceof Error ? error.message : String(error),
                },
              ],
              isError: true,
            };
          }
        }
      },
    );

    this._toolHandlersInitialized = true;
  }

  private _completionHandlerInitialized = false;

  private setCompletionRequestHandler() {
    if (this._completionHandlerInitialized) {
      return;
    }

    this.server.assertCanSetRequestHandler(
      CompleteRequestSchema.shape.method.value,
    );

    this.server.setRequestHandler(
      CompleteRequestSchema,
      async (request): Promise<CompleteResult> => {
        switch (request.params.ref.type) {
          case "ref/prompt":
            return this.handlePromptCompletion(request, request.params.ref);

          case "ref/resource":
            return this.handleResourceCompletion(request, request.params.ref);

          default:
            throw new McpError(
              ErrorCode.InvalidParams,
              `Invalid completion reference: ${request.params.ref}`,
            );
        }
      },
    );

    this._completionHandlerInitialized = true;
  }

  private async handlePromptCompletion(
    request: CompleteRequest,
    ref: PromptReference,
  ): Promise<CompleteResult> {
    const prompt = this._registeredPrompts[ref.name];
    if (!prompt) {
      throw new McpError(
        ErrorCode.InvalidParams,
        `Prompt ${request.params.ref.name} not found`,
      );
    }

    if (!prompt.argsSchema) {
      return EMPTY_COMPLETION_RESULT;
    }

    const field = prompt.argsSchema.shape[request.params.argument.name];
    if (!(field instanceof Completable)) {
      return EMPTY_COMPLETION_RESULT;
    }

    const def: CompletableDef<ZodString> = field._def;
    const suggestions = await def.complete(request.params.argument.value);
    return createCompletionResult(suggestions);
  }

  private async handleResourceCompletion(
    request: CompleteRequest,
    ref: ResourceReference,
  ): Promise<CompleteResult> {
    const template = Object.values(this._registeredResourceTemplates).find(
      (t) => t.resourceTemplate.uriTemplate.toString() === ref.uri,
    );

    if (!template) {
      if (this._registeredResources[ref.uri]) {
        // Attempting to autocomplete a fixed resource URI is not an error in the spec (but probably should be).
        return EMPTY_COMPLETION_RESULT;
      }

      throw new McpError(
        ErrorCode.InvalidParams,
        `Resource template ${request.params.ref.uri} not found`,
      );
    }

    const completer = template.resourceTemplate.completeCallback(
      request.params.argument.name,
    );
    if (!completer) {
      return EMPTY_COMPLETION_RESULT;
    }

    const suggestions = await completer(request.params.argument.value);
    return createCompletionResult(suggestions);
  }

  private _resourceHandlersInitialized = false;

  private setResourceRequestHandlers() {
    if (this._resourceHandlersInitialized) {
      return;
    }

    this.server.assertCanSetRequestHandler(
      ListResourcesRequestSchema.shape.method.value,
    );
    this.server.assertCanSetRequestHandler(
      ListResourceTemplatesRequestSchema.shape.method.value,
    );
    this.server.assertCanSetRequestHandler(
      ReadResourceRequestSchema.shape.method.value,
    );

    this.server.registerCapabilities({
      resources: {},
    });

    this.server.setRequestHandler(
      ListResourcesRequestSchema,
      async (request, extra) => {
        const resources = Object.entries(this._registeredResources).map(
          ([uri, resource]) => ({
            uri,
            name: resource.name,
            ...resource.metadata,
          }),
        );

        const templateResources: Resource[] = [];
        for (const template of Object.values(
          this._registeredResourceTemplates,
        )) {
          if (!template.resourceTemplate.listCallback) {
            continue;
          }

          const result = await template.resourceTemplate.listCallback(extra);
          for (const resource of result.resources) {
            templateResources.push({
              ...resource,
              ...template.metadata,
            });
          }
        }

        return { resources: [...resources, ...templateResources] };
      },
    );

    this.server.setRequestHandler(
      ListResourceTemplatesRequestSchema,
      async () => {
        const resourceTemplates = Object.entries(
          this._registeredResourceTemplates,
        ).map(([name, template]) => ({
          name,
          uriTemplate: template.resourceTemplate.uriTemplate.toString(),
          ...template.metadata,
        }));

        return { resourceTemplates };
      },
    );

    this.server.setRequestHandler(
      ReadResourceRequestSchema,
      async (request, extra) => {
        const uri = new URL(request.params.uri);

        // First check for exact resource match
        const resource = this._registeredResources[uri.toString()];
        if (resource) {
          return resource.readCallback(uri, extra);
        }

        // Then check templates
        for (const template of Object.values(
          this._registeredResourceTemplates,
        )) {
          const variables = template.resourceTemplate.uriTemplate.match(
            uri.toString(),
          );
          if (variables) {
            return template.readCallback(uri, variables, extra);
          }
        }

        throw new McpError(
          ErrorCode.InvalidParams,
          `Resource ${uri} not found`,
        );
      },
    );

    this.setCompletionRequestHandler();
    
    this._resourceHandlersInitialized = true;
  }

  private _promptHandlersInitialized = false;

  private setPromptRequestHandlers() {
    if (this._promptHandlersInitialized) {
      return;
    }

    this.server.assertCanSetRequestHandler(
      ListPromptsRequestSchema.shape.method.value,
    );
    this.server.assertCanSetRequestHandler(
      GetPromptRequestSchema.shape.method.value,
    );

    this.server.registerCapabilities({
      prompts: {},
    });

    this.server.setRequestHandler(
      ListPromptsRequestSchema,
      (): ListPromptsResult => ({
        prompts: Object.entries(this._registeredPrompts).map(
          ([name, prompt]): Prompt => {
            return {
              name,
              description: prompt.description,
              arguments: prompt.argsSchema
                ? promptArgumentsFromSchema(prompt.argsSchema)
                : undefined,
            };
          },
        ),
      }),
    );

    this.server.setRequestHandler(
      GetPromptRequestSchema,
      async (request, extra): Promise<GetPromptResult> => {
        const prompt = this._registeredPrompts[request.params.name];
        if (!prompt) {
          throw new McpError(
            ErrorCode.InvalidParams,
            `Prompt ${request.params.name} not found`,
          );
        }

        if (prompt.argsSchema) {
          const parseResult = await prompt.argsSchema.safeParseAsync(
            request.params.arguments,
          );
          if (!parseResult.success) {
            throw new McpError(
              ErrorCode.InvalidParams,
              `Invalid arguments for prompt ${request.params.name}: ${parseResult.error.message}`,
            );
          }

          const args = parseResult.data;
          const cb = prompt.callback as PromptCallback<PromptArgsRawShape>;
          return await Promise.resolve(cb(args, extra));
        } else {
          const cb = prompt.callback as PromptCallback<undefined>;
          return await Promise.resolve(cb(extra));
        }
      },
    );

    this.setCompletionRequestHandler();
    
    this._promptHandlersInitialized = true;
  }

  /**
   * Registers a resource `name` at a fixed URI, which will use the given callback to respond to read requests.
   */
  resource(name: string, uri: string, readCallback: ReadResourceCallback): void;

  /**
   * Registers a resource `name` at a fixed URI with metadata, which will use the given callback to respond to read requests.
   */
  resource(
    name: string,
    uri: string,
    metadata: ResourceMetadata,
    readCallback: ReadResourceCallback,
  ): void;

  /**
   * Registers a resource `name` with a template pattern, which will use the given callback to respond to read requests.
   */
  resource(
    name: string,
    template: ResourceTemplate,
    readCallback: ReadResourceTemplateCallback,
  ): void;

  /**
   * Registers a resource `name` with a template pattern and metadata, which will use the given callback to respond to read requests.
   */
  resource(
    name: string,
    template: ResourceTemplate,
    metadata: ResourceMetadata,
    readCallback: ReadResourceTemplateCallback,
  ): void;

  resource(
    name: string,
    uriOrTemplate: string | ResourceTemplate,
    ...rest: unknown[]
  ): void {
    let metadata: ResourceMetadata | undefined;
    if (typeof rest[0] === "object") {
      metadata = rest.shift() as ResourceMetadata;
    }

    const readCallback = rest[0] as
      | ReadResourceCallback
      | ReadResourceTemplateCallback;

    if (typeof uriOrTemplate === "string") {
      if (this._registeredResources[uriOrTemplate]) {
        throw new Error(`Resource ${uriOrTemplate} is already registered`);
      }

      this._registeredResources[uriOrTemplate] = {
        name,
        metadata,
        readCallback: readCallback as ReadResourceCallback,
      };
    } else {
      if (this._registeredResourceTemplates[name]) {
        throw new Error(`Resource template ${name} is already registered`);
      }

      this._registeredResourceTemplates[name] = {
        resourceTemplate: uriOrTemplate,
        metadata,
        readCallback: readCallback as ReadResourceTemplateCallback,
      };
    }

    this.setResourceRequestHandlers();
  }

  /**
   * Registers a zero-argument tool `name`, which will run the given function when the client calls it.
   */
  tool(name: string, cb: ToolCallback): void;

  /**
   * Registers a zero-argument tool `name` (with a description) which will run the given function when the client calls it.
   */
  tool(name: string, description: string, cb: ToolCallback): void;

  /**
   * Registers a tool `name` accepting the given arguments, which must be an object containing named properties associated with Zod schemas. When the client calls it, the function will be run with the parsed and validated arguments.
   */
  tool<Args extends ZodRawShape>(
    name: string,
    paramsSchema: Args,
    cb: ToolCallback<Args>,
  ): void;

  /**
   * Registers a tool `name` (with a description) accepting the given arguments, which must be an object containing named properties associated with Zod schemas. When the client calls it, the function will be run with the parsed and validated arguments.
   */
  tool<Args extends ZodRawShape>(
    name: string,
    description: string,
    paramsSchema: Args,
    cb: ToolCallback<Args>,
  ): void;

  tool(name: string, ...rest: unknown[]): void {
    if (this._registeredTools[name]) {
      throw new Error(`Tool ${name} is already registered`);
    }

    let description: string | undefined;
    if (typeof rest[0] === "string") {
      description = rest.shift() as string;
    }

    let paramsSchema: ZodRawShape | undefined;
    if (rest.length > 1) {
      paramsSchema = rest.shift() as ZodRawShape;
    }

    const cb = rest[0] as ToolCallback<ZodRawShape | undefined>;
    this._registeredTools[name] = {
      description,
      inputSchema:
        paramsSchema === undefined ? undefined : z.object(paramsSchema),
      callback: cb,
    };

    this.setToolRequestHandlers();
  }

  /**
   * Removes a registered tool by name.
   * @param name - The name of the tool to remove.
   * @returns boolean - Returns true if the tool was removed, false if the tool was not found.
   */
  removeTool(name: string): boolean {
    if (this._registeredTools[name]) {
      delete this._registeredTools[name];
      return true;
    }
    return false;
  }

  /**
   * Registers a zero-argument prompt `name`, which will run the given function when the client calls it.
   */
  prompt(name: string, cb: PromptCallback): void;

  /**
   * Registers a zero-argument prompt `name` (with a description) which will run the given function when the client calls it.
   */
  prompt(name: string, description: string, cb: PromptCallback): void;

  /**
   * Registers a prompt `name` accepting the given arguments, which must be an object containing named properties associated with Zod schemas. When the client calls it, the function will be run with the parsed and validated arguments.
   */
  prompt<Args extends PromptArgsRawShape>(
    name: string,
    argsSchema: Args,
    cb: PromptCallback<Args>,
  ): void;

  /**
   * Registers a prompt `name` (with a description) accepting the given arguments, which must be an object containing named properties associated with Zod schemas. When the client calls it, the function will be run with the parsed and validated arguments.
   */
  prompt<Args extends PromptArgsRawShape>(
    name: string,
    description: string,
    argsSchema: Args,
    cb: PromptCallback<Args>,
  ): void;

  prompt(name: string, ...rest: unknown[]): void {
    if (this._registeredPrompts[name]) {
      throw new Error(`Prompt ${name} is already registered`);
    }

    let description: string | undefined;
    if (typeof rest[0] === "string") {
      description = rest.shift() as string;
    }

    let argsSchema: PromptArgsRawShape | undefined;
    if (rest.length > 1) {
      argsSchema = rest.shift() as PromptArgsRawShape;
    }

    const cb = rest[0] as PromptCallback<PromptArgsRawShape | undefined>;
    this._registeredPrompts[name] = {
      description,
      argsSchema: argsSchema === undefined ? undefined : z.object(argsSchema),
      callback: cb,
    };

    this.setPromptRequestHandlers();
  }
}

/**
 * A callback to complete one variable within a resource template's URI template.
 */
export type CompleteResourceTemplateCallback = (
  value: string,
) => string[] | Promise<string[]>;

/**
 * A resource template combines a URI pattern with optional functionality to enumerate
 * all resources matching that pattern.
 */
export class ResourceTemplate {
  private _uriTemplate: UriTemplate;

  constructor(
    uriTemplate: string | UriTemplate,
    private _callbacks: {
      /**
       * A callback to list all resources matching this template. This is required to specified, even if `undefined`, to avoid accidentally forgetting resource listing.
       */
      list: ListResourcesCallback | undefined;

      /**
       * An optional callback to autocomplete variables within the URI template. Useful for clients and users to discover possible values.
       */
      complete?: {
        [variable: string]: CompleteResourceTemplateCallback;
      };
    },
  ) {
    this._uriTemplate =
      typeof uriTemplate === "string"
        ? new UriTemplate(uriTemplate)
        : uriTemplate;
  }

  /**
   * Gets the URI template pattern.
   */
  get uriTemplate(): UriTemplate {
    return this._uriTemplate;
  }

  /**
   * Gets the list callback, if one was provided.
   */
  get listCallback(): ListResourcesCallback | undefined {
    return this._callbacks.list;
  }

  /**
   * Gets the callback for completing a specific URI template variable, if one was provided.
   */
  completeCallback(
    variable: string,
  ): CompleteResourceTemplateCallback | undefined {
    return this._callbacks.complete?.[variable];
  }
}

/**
 * Callback for a tool handler registered with Server.tool().
 *
 * Parameters will include tool arguments, if applicable, as well as other request handler context.
 */
export type ToolCallback<Args extends undefined | ZodRawShape = undefined> =
  Args extends ZodRawShape
    ? (
        args: z.objectOutputType<Args, ZodTypeAny>,
        extra: RequestHandlerExtra,
      ) => CallToolResult | Promise<CallToolResult>
    : (extra: RequestHandlerExtra) => CallToolResult | Promise<CallToolResult>;

type RegisteredTool = {
  description?: string;
  inputSchema?: AnyZodObject;
  callback: ToolCallback<undefined | ZodRawShape>;
};

const EMPTY_OBJECT_JSON_SCHEMA = {
  type: "object" as const,
};

/**
 * Additional, optional information for annotating a resource.
 */
export type ResourceMetadata = Omit<Resource, "uri" | "name">;

/**
 * Callback to list all resources matching a given template.
 */
export type ListResourcesCallback = (
  extra: RequestHandlerExtra,
) => ListResourcesResult | Promise<ListResourcesResult>;

/**
 * Callback to read a resource at a given URI.
 */
export type ReadResourceCallback = (
  uri: URL,
  extra: RequestHandlerExtra,
) => ReadResourceResult | Promise<ReadResourceResult>;

type RegisteredResource = {
  name: string;
  metadata?: ResourceMetadata;
  readCallback: ReadResourceCallback;
};

/**
 * Callback to read a resource at a given URI, following a filled-in URI template.
 */
export type ReadResourceTemplateCallback = (
  uri: URL,
  variables: Variables,
  extra: RequestHandlerExtra,
) => ReadResourceResult | Promise<ReadResourceResult>;

type RegisteredResourceTemplate = {
  resourceTemplate: ResourceTemplate;
  metadata?: ResourceMetadata;
  readCallback: ReadResourceTemplateCallback;
};

type PromptArgsRawShape = {
  [k: string]:
    | ZodType<string, ZodTypeDef, string>
    | ZodOptional<ZodType<string, ZodTypeDef, string>>;
};

export type PromptCallback<
  Args extends undefined | PromptArgsRawShape = undefined,
> = Args extends PromptArgsRawShape
  ? (
      args: z.objectOutputType<Args, ZodTypeAny>,
      extra: RequestHandlerExtra,
    ) => GetPromptResult | Promise<GetPromptResult>
  : (extra: RequestHandlerExtra) => GetPromptResult | Promise<GetPromptResult>;

type RegisteredPrompt = {
  description?: string;
  argsSchema?: ZodObject<PromptArgsRawShape>;
  callback: PromptCallback<undefined | PromptArgsRawShape>;
};

function promptArgumentsFromSchema(
  schema: ZodObject<PromptArgsRawShape>,
): PromptArgument[] {
  return Object.entries(schema.shape).map(
    ([name, field]): PromptArgument => ({
      name,
      description: field.description,
      required: !field.isOptional(),
    }),
  );
}

function createCompletionResult(suggestions: string[]): CompleteResult {
  return {
    completion: {
      values: suggestions.slice(0, 100),
      total: suggestions.length,
      hasMore: suggestions.length > 100,
    },
  };
}

const EMPTY_COMPLETION_RESULT: CompleteResult = {
  completion: {
    values: [],
    hasMore: false,
  },
};

```

--------------------------------------------------------------------------------
/main/index.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node

import { McpServer } from "./mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { z } from "zod";
import path from "path";
import { fileURLToPath } from "url";
import { readFileSync, existsSync } from "fs";

// Get the directory where the contextmanager is located
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Domain interfaces
interface DomainInfo {
  name: string;
  description: string;
  entityTypes: string[];
  host?: string;
  port?: number;
  path?: string;
  command?: string;
  args?: string[];
}

interface FlowInfo {
  id: string;
  domain: string;
  entityName?: string;
  entityType?: string;
  active: boolean;
  createdAt: number;
}

// Domain client class
class DomainClient {
  public name: string;
  public client: Client | null = null;
  public transport: SSEClientTransport | StdioClientTransport | null = null;
  public connected: boolean = false;
  private process: any = null;

  constructor(public domain: DomainInfo) {
    this.name = domain.name;
  }

  async connect(): Promise<boolean> {
    if (this.connected) {
      return true;
    }

    try {
      // Create client
      this.client = new Client(
        {
          name: `contextmanager-${this.name}-client`,
          version: "1.0.0"
        },
        {
          capabilities: {
            resources: {},
            tools: {},
            prompts: {}
          }
        }
      );

      // Connect to domain server
      if (this.domain.host && this.domain.port) {
        // Connect via SSE
        const url = new URL(`http://${this.domain.host}:${this.domain.port}${this.domain.path || '/sse'}`);
        this.transport = new SSEClientTransport(url);
      } else if (this.domain.command) {
        // Connect via stdio
        this.transport = new StdioClientTransport({
          command: this.domain.command,
          args: this.domain.args || [],
        });
      } else {
        console.error(`Domain ${this.name} has no connection information`);
        return false;
      }

      await this.client.connect(this.transport);
      this.connected = true;
      return true;
    } catch (error) {
      console.error(`Failed to connect to domain ${this.name}:`, error);
      this.connected = false;
      return false;
    }
  }

  async disconnect(): Promise<void> {
    if (!this.connected) {
      return;
    }

    try {
      if (this.client) {
        // Manually close the transport as there's no official disconnect method
        if (this.transport) {
          if ('close' in this.transport) {
            await (this.transport as any).close();
          }
        }
      }
      this.connected = false;
    } catch (error) {
      console.error(`Error disconnecting from domain ${this.name}:`, error);
    }
  }

  async callTool(toolRequest: { name: string; arguments: any }): Promise<any> {
    if (!this.connected || !this.client) {
      const connected = await this.connect();
      if (!connected) {
        return {
          content: [{ type: "text", text: `Error: Not connected to domain ${this.name}` }],
          isError: true
        };
      }
    }

    try {
      if (!this.client) {
        throw new Error(`Client for domain ${this.name} is not initialized`);
      }
      
      const result = await this.client.callTool(toolRequest);
      return result;
    } catch (error) {
      console.error(`Error calling tool ${toolRequest.name} on domain ${this.name}:`, error);
      return {
        content: [{ type: "text", text: `Error calling tool ${toolRequest.name} on domain ${this.name}: ${error}` }],
        isError: true
      };
    }
  }

  async readResource(resourceRequest: { uri: string }): Promise<any> {
    if (!this.connected || !this.client) {
      const connected = await this.connect();
      if (!connected) {
        return {
          contents: [{
            uri: resourceRequest.uri,
            text: `Error: Not connected to domain ${this.name}`
          }]
        };
      }
    }

    try {
      if (!this.client) {
        throw new Error(`Client for domain ${this.name} is not initialized`);
      }
      
      return await this.client.readResource(resourceRequest);
    } catch (error) {
      console.error(`Error reading resource ${resourceRequest.uri} from domain ${this.name}:`, error);
      return {
        contents: [{
          uri: resourceRequest.uri,
          text: `Error reading resource: ${error}`
        }]
      };
    }
  }
}

// In-memory storage
const domains: DomainInfo[] = [
  {
    name: "developer",
    description: "Software development context with entities like projects, components, and tasks",
    entityTypes: ["project", "component", "task", "issue", "commit"],
    command: "node",
    args: [path.resolve(__dirname, "../developer/index.js")]
  },
  {
    name: "project",
    description: "Project management context with entities like projects, tasks, and resources",
    entityTypes: ["project", "task", "resource", "milestone", "risk"],
    command: "node",
    args: [path.resolve(__dirname, "../project/index.js")]
  },
  {
    name: "student",
    description: "Educational context with entities like courses, assignments, and exams",
    entityTypes: ["course", "assignment", "exam", "note", "grade"],
    command: "node",
    args: [path.resolve(__dirname, "../student/index.js")]
  },
  {
    name: "qualitativeresearch",
    description: "Qualitative research context with entities like studies, participants, and interviews",
    entityTypes: ["study", "participant", "interview", "code", "theme"],
    command: "node",
    args: [path.resolve(__dirname, "../qualitativeresearch/index.js")]
  },
  {
    name: "quantitativeresearch",
    description: "Quantitative research context with entities like datasets, variables, and analyses",
    entityTypes: ["dataset", "variable", "analysis", "model", "result"],
    command: "node",
    args: [path.resolve(__dirname, "../quantitativeresearch/index.js")]
  }
];

// Domain clients
const domainClients: { [key: string]: DomainClient } = {};

// Initialize domain clients
for (const domain of domains) {
  domainClients[domain.name] = new DomainClient(domain);
}

// In-memory flow management
const flows: FlowInfo[] = [];
let activeDomain: string | null = null;
let flowCounter = 0;

// Function to get tool description based on active domain
function getToolDescription(toolName: string, domain: string | null): string {
  if (!domain) {
    domain = "common";
  }
  
  const descriptionFilePath = path.resolve(
    __dirname,
    "descriptions",
    `${domain}_${toolName}.txt`
  );
  
  try {
    if (existsSync(descriptionFilePath)) {
      return readFileSync(descriptionFilePath, "utf8");
    } else {
      console.warn(`Description file not found: ${descriptionFilePath}`);
      return `${toolName} tool for ${domain} domain`;
    }
  } catch (error) {
    console.error(`Error reading description file for ${domain}_${toolName}:`, error);
    return `${toolName} tool for ${domain} domain`;
  }
}

// Create an MCP server
const server = new McpServer({
  name: "Context Manager",
  version: "1.0.0"
});

// Store tool schemas and callbacks for re-registration when domain changes
const toolDefinitions: {
  [key: string]: {
    schema: any;
    callback: (...args: any[]) => Promise<any>;
  }
} = {};

// Function to register or update a tool with domain-specific description
function registerDomainTool(
  name: string, 
  schema: any, 
  callback: (...args: any[]) => Promise<any>
): void {
  // Store the tool definition for later re-registration
  toolDefinitions[name] = {
    schema,
    callback
  };
  
  // Register the tool with the current domain description
  server.tool(
    name,
    getToolDescription(name, activeDomain),
    schema,
    callback
  );
}

// Function to update all tool descriptions when domain changes
function updateDomainToolDescriptions(): void {
  // Re-register all stored tools with new descriptions
  for (const [name, definition] of Object.entries(toolDefinitions)) {
    server.removeTool(name);
    server.tool(
      name,
      getToolDescription(name, activeDomain),
      definition.schema,
      definition.callback
    );
  }
}

// Domain management tools
server.tool(
  "setActiveDomain",
  "Change the active domain for subsequent tool calls",
  { domain: z.string() },
  async ({ domain }) => {
    const foundDomain = domains.find(d => d.name.toLowerCase() === domain.toLowerCase());
    if (!foundDomain) {
      return {
        content: [{ type: "text", text: `Error: Domain '${domain}' not found. Available domains: ${domains.map(d => d.name).join(", ")}` }],
        isError: true
      };
    }
    
    // Connect to the domain server
    const domainClient = domainClients[foundDomain.name];
    const connected = await domainClient.connect();
    
    if (!connected) {
      return {
        content: [{ type: "text", text: `Error: Could not connect to domain server for '${domain}'` }],
        isError: true
      };
    }
    
    activeDomain = foundDomain.name;
    
    // Update tool descriptions for the new active domain
    updateDomainToolDescriptions();
    
    return {
      content: [{ type: "text", text: `Active domain set to: ${activeDomain}` }]
    };
  }
);

// Flow management tools
registerDomainTool(
  "startsession",
  { 
    domain: z.string()
  },
  async ({ domain }) => {
    const foundDomain = domains.find(d => d.name.toLowerCase() === domain.toLowerCase());
    if (!foundDomain) {
      return {
        content: [{ type: "text", text: `Error: Domain '${domain}' not found. Available domains: ${domains.map(d => d.name).join(", ")}` }],
        isError: true
      };
    }
    
    // Connect to the domain server
    const domainClient = domainClients[foundDomain.name];
    const connected = await domainClient.connect();
    
    if (!connected) {
      return {
        content: [{ type: "text", text: `Error: Could not connect to domain server for '${domain}'` }],
        isError: true
      };
    }
    
    activeDomain = foundDomain.name;
    flowCounter++;

    // Update tool descriptions for the new active domain since activeDomain changed
    updateDomainToolDescriptions();

    // Forward the startsession call to the domain server with a domain-specific session identifier
    try {
      const result = await domainClient.callTool({
        name: "startsession",
        arguments: {}
      });

      const lastWord = result.content[0].text.split(' ').pop();
      // Create a contextmanager flow ID from domain session ID (last word)
      const flowId = `flow_${lastWord}`;

      flows.push({
        id: flowId,
        domain: activeDomain,
        active: true,
        createdAt: Date.now()
      });
      
      return {
        content: [
          { type: "text", text: `${result.content[0].text}`}
        ],
      };
    } catch (error) {
      console.error(`Error starting session for domain ${activeDomain}:`, error);
      return {
        content: [{ type: "text", text: `Error starting session for domain ${activeDomain}: ${error}` }],
        isError: true
      };
    }
  }
);

registerDomainTool(
  "endsession",
  {
    sessionId: z.string(),
    stage: z.string(),
    stageNumber: z.number(),
    totalStages: z.number(),
    nextStageNeeded: z.boolean(),
    analysis: z.string().optional(),
    isRevision: z.boolean().optional(),
    revisesStage: z.number().optional(),
    stageData: z.record(z.string(), z.any()).optional()
  },
  async ({ sessionId, stage, stageNumber, totalStages, nextStageNeeded, analysis, isRevision, revisesStage, stageData }) => {
    const flowId = `flow_${sessionId}`;
    const flowIndex = flows.findIndex(s => s.id === flowId);
    if (flowIndex === -1) {
      return {
        content: [{ type: "text", text: `Error: Context Manager flow with ID '${flowId}' not found.` }],
        isError: true
      };
    }
    
    const flow = flows[flowIndex];
    const domainName = flow.domain;
    const domainClient = domainClients[domainName];
    
    if (!domainClient || !domainClient.connected) {
      const connected = await domainClient.connect();
      if (!connected) {
        return {
          content: [{ type: "text", text: `Error: Could not connect to domain server for '${domainName}'` }],
          isError: true
        };
      }
    }
    
    // Forward the endsession call to the domain server
    try {
      const result = await domainClient.callTool({
        name: "endsession",
        arguments: {
          sessionId: sessionId,
          stage,
          stageNumber,
          totalStages,
          nextStageNeeded,
          analysis,
          isRevision,
          revisesStage,
          stageData
        }
      });
      
      if (!nextStageNeeded) {
        flows[flowIndex].active = false;
        return {
          content: [{ type: "text", text: `${result.content[0].text}`}]
        }
      }
      
      return {
        content: [{ type: "text", text: `${result.content[0].text}` }]
      };
    } catch (error) {
      console.error(`Error ending session for domain ${domainName}:`, error);
      return {
        content: [{ type: "text", text: `Error ending session for domain ${domainName}: ${error}` }],
        isError: true
      };
    }
  }
);

// Context management tools
registerDomainTool(
  "buildcontext",
  {
    type: z.enum(["entities", "relations", "observations"]),
    data: z.array(z.any())
  },
  async ({ type, data }) => {
    if (!activeDomain) {
      return {
        content: [{ type: "text", text: "Error: No active domain set. Use setActiveDomain or startsession tool first." }],
        isError: true
      };
    }

    const domainClient = domainClients[activeDomain];
    
    if (!domainClient || !domainClient.connected) {
      const connected = await domainClient.connect();
      if (!connected) {
        return {
          content: [{ type: "text", text: `Error: Could not connect to domain server for '${activeDomain}'` }],
          isError: true
        };
      }
    }
    
    // Forward the buildcontext call to the domain server
    try {
      const result = await domainClient.callTool({
        name: "buildcontext",
        arguments: {
          type,
          data
        }
      });
      
      return result;
    } catch (error) {
      console.error(`Error building context for domain ${activeDomain}:`, error);
      return {
        content: [{ type: "text", text: `Error building context for domain ${activeDomain}: ${error}` }],
        isError: true
      };
    }
  }
);

registerDomainTool(
  "deletecontext",
  {
    type: z.enum(["entities", "relations", "observations"]),
    data: z.array(z.any())
  },
  async ({ type, data }) => {
    if (!activeDomain) {
      return {
        content: [{ type: "text", text: "Error: No active domain set. Use setActiveDomain or startsession tool first." }],
        isError: true
      };
    }

    const domainClient = domainClients[activeDomain];
    
    if (!domainClient || !domainClient.connected) {
      const connected = await domainClient.connect();
      if (!connected) {
        return {
          content: [{ type: "text", text: `Error: Could not connect to domain server for '${activeDomain}'` }],
          isError: true
        };
      }
    }
    
    // Forward the deletecontext call to the domain server
    try {
      const result = await domainClient.callTool({
        name: "deletecontext",
        arguments: {
          type,
          data
        }
      });
      
      return result;
    } catch (error) {
      console.error(`Error deleting context for domain ${activeDomain}:`, error);
      return {
        content: [{ type: "text", text: `Error deleting context for domain ${activeDomain}: ${error}` }],
        isError: true
      };
    }
  }
);

registerDomainTool(
  "loadcontext",
  {
    entityName: z.string(),
    entityType: z.string().optional(),
    sessionId: z.string().optional()
  },
  async ({ entityName, entityType, sessionId }) => {
    if (!activeDomain) {
      return {
        content: [{ type: "text", text: "Error: No active domain set. Use setActiveDomain or startsession tool first." }],
        isError: true
      };
    }

    const flowId = `flow_${sessionId}`;

    // Find active contextmanager flow or use provided sessionId
    let targetFlow: FlowInfo | undefined;
    if (sessionId) {
      targetFlow = flows.find(s => s.id === flowId);
    } else {
      targetFlow = flows.find(s => s.domain === activeDomain && s.active);
    }

    if (!targetFlow) {
      return {
        content: [{ type: "text", text: "Error: No active Context Manager flow found. Start a flow first." }],
        isError: true
      };
    }

    const domainClient = domainClients[activeDomain];
    
    if (!domainClient || !domainClient.connected) {
      const connected = await domainClient.connect();
      if (!connected) {
        return {
          content: [{ type: "text", text: `Error: Could not connect to domain server for '${activeDomain}'` }],
          isError: true
        };
      }
    }
    
    // Update contextmanager flow with entity details
    targetFlow.entityName = entityName;
    targetFlow.entityType = entityType || "unknown";

    // Forward the loadcontext call to the domain server
    try {
      const result = await domainClient.callTool({
        name: "loadcontext",
        arguments: {
          entityName,
          entityType,
          sessionId: sessionId
        }
      });
      
      return {
        content: [{ 
          type: "text", 
          text: `${result.content[0].text}`
        }]
      };
    } catch (error) {
      console.error(`Error loading context for domain ${activeDomain}:`, error);
      return {
        content: [{ type: "text", text: `Error loading context for domain ${activeDomain}: ${error}` }],
        isError: true
      };
    }
  }
);

registerDomainTool(
  "advancedcontext",
  {
    type: z.string(),
    params: z.record(z.string(), z.any())
  },
  async ({ type, params }) => {
    if (!activeDomain) {
      return {
        content: [{ type: "text", text: "Error: No active domain set. Use setActiveDomain or startsession tool first." }],
        isError: true
      };
    }

    const domainClient = domainClients[activeDomain];
    
    if (!domainClient || !domainClient.connected) {
      const connected = await domainClient.connect();
      if (!connected) {
        return {
          content: [{ type: "text", text: `Error: Could not connect to domain server for '${activeDomain}'` }],
          isError: true
        };
      }
    }
    
    // Forward the advancedcontext call to the domain server
    try {
      const result = await domainClient.callTool({
        name: "advancedcontext",
        arguments: {
          type,
          params
        }
      });
      
      return result;
    } catch (error) {
      console.error(`Error performing advanced context operation for domain ${activeDomain}:`, error);
      return {
        content: [{ type: "text", text: `Error performing advanced context operation for domain ${activeDomain}: ${error}` }],
        isError: true
      };
    }
  }
);

// // List all entities
// server.tool(
//   "listAllEntities",
//   {
//     domain: z.string().optional()
//   },
//   async () => {
//     if (!activeDomain) {
//       return {
//         content: [{ type: "text", text: "Error: No active domain set. Use setActiveDomain or startsession tool first." }],
//         isError: true
//       };
//     }

//     const domainClient = domainClients[activeDomain];
    
//     if (!domainClient || !domainClient.connected) {
//       const connected = await domainClient.connect();
//       if (!connected) {
//         return {
//           content: [{ type: "text", text: `Error: Could not connect to domain server for '${activeDomain}'` }],
//           isError: true
//         };
//       }
//     }
    
//     // Forward the listAllEntities call to the domain server
//     try {
//       const result = await domainClient.callTool({
//         name: "listAllEntities",
//         arguments: {}
//       });
      
//       return result;
//     } catch (error) {
//       // If the domain server doesn't support listAllEntities, fall back to our domain registry
//       const domain = domains.find(d => d.name === activeDomain);
//       if (!domain) {
//         return {
//           content: [{ type: "text", text: `Error: Domain '${activeDomain}' not found.` }],
//           isError: true
//         };
//       }

//       return {
//         content: [{ 
//           type: "text", 
//           text: `Available entity types in ${activeDomain} domain: ${domain.entityTypes.join(", ")}` 
//         }]
//       };
//     }
//   }
// );

// Domain discovery resources
server.resource(
  "domains",
  "domains://list",
  async (uri) => ({
    contents: [{
      uri: uri.href,
      text: JSON.stringify(domains, null, 2)
    }]
  })
);

// Cross-domain functionality
server.tool(
  "relateCrossDomain",
  "Create connections between entities across different domains",
  {
    fromDomain: z.string(),
    fromEntity: z.string(),
    toDomain: z.string(),
    toEntity: z.string(),
    relationType: z.string()
  },
  async ({ fromDomain, fromEntity, toDomain, toEntity, relationType }) => {
    // Validate domains
    const fromDomainInfo = domains.find(d => d.name.toLowerCase() === fromDomain.toLowerCase());
    const toDomainInfo = domains.find(d => d.name.toLowerCase() === toDomain.toLowerCase());
    
    if (!fromDomainInfo) {
      return {
        content: [{ type: "text", text: `Error: Source domain '${fromDomain}' not found.` }],
        isError: true
      };
    }
    
    if (!toDomainInfo) {
      return {
        content: [{ type: "text", text: `Error: Target domain '${toDomain}' not found.` }],
        isError: true
      };
    }
    
    // Create cross-domain relation by adding observations to both entities
    try {
      // Connect to source domain
      const fromDomainClient = domainClients[fromDomainInfo.name];
      if (!fromDomainClient || !fromDomainClient.connected) {
        const connected = await fromDomainClient.connect();
        if (!connected) {
          return {
            content: [{ type: "text", text: `Error: Could not connect to domain server for '${fromDomain}'` }],
            isError: true
          };
        }
      }
      
      // Connect to target domain
      const toDomainClient = domainClients[toDomainInfo.name];
      if (!toDomainClient || !toDomainClient.connected) {
        const connected = await toDomainClient.connect();
        if (!connected) {
          return {
            content: [{ type: "text", text: `Error: Could not connect to domain server for '${toDomain}'` }],
            isError: true
          };
        }
      }
      
      // Add observation to source entity about relation to target entity
      await fromDomainClient.callTool({
        name: "buildcontext",
        arguments: {
          type: "observations",
          data: {
            observations: [
              {
                entityName: fromEntity,
                contents: [`Related to ${toEntity} (${toDomainInfo.name} domain) via ${relationType}`]
              }
            ]
          }
        }
      });
      
      // Add observation to target entity about relation from source entity
      await toDomainClient.callTool({
        name: "buildcontext",
        arguments: {
          type: "observations",
          data: {
            observations: [
              {
                entityName: toEntity,
                contents: [`Related from ${fromEntity} (${fromDomainInfo.name} domain) via ${relationType}`]
              }
            ]
          }
        }
      });
      
      return {
        content: [{ 
          type: "text", 
          text: `Created cross-domain relation: ${fromEntity} (${fromDomain}) --[${relationType}]--> ${toEntity} (${toDomain})` 
        }]
      };
    } catch (error) {
      console.error(`Error creating cross-domain relation:`, error);
      return {
        content: [{ type: "text", text: `Error creating cross-domain relation: ${error}` }],
        isError: true
      };
    }
  }
);

// Main function to start the server
async function main() {
  // Start receiving messages on stdin and sending messages on stdout
  const transport = new StdioServerTransport();
  await server.connect(transport);
}

// Execute the main function
main().catch(error => {
  console.error("Error in contextmanager:", error);
  process.exit(1);
}); 
```

--------------------------------------------------------------------------------
/developer/index.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { promises as fs } from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'url';
import { z } from "zod";
import { readFileSync, existsSync } from "fs";

// Define memory file path using environment variable with fallback
const parentPath = path.dirname(fileURLToPath(import.meta.url));
const defaultMemoryPath = path.join(parentPath, 'memory.json');
const defaultSessionsPath = path.join(parentPath, 'sessions.json');

// Properly handle absolute and relative paths for MEMORY_FILE_PATH
const MEMORY_FILE_PATH = process.env.MEMORY_FILE_PATH
  ? path.isAbsolute(process.env.MEMORY_FILE_PATH)
    ? process.env.MEMORY_FILE_PATH  // Use absolute path as is
    : path.join(process.cwd(), process.env.MEMORY_FILE_PATH)  // Relative to current working directory
  : defaultMemoryPath;  // Default fallback

// Properly handle absolute and relative paths for SESSIONS_FILE_PATH
const SESSIONS_FILE_PATH = process.env.SESSIONS_FILE_PATH
  ? path.isAbsolute(process.env.SESSIONS_FILE_PATH)
    ? process.env.SESSIONS_FILE_PATH  // Use absolute path as is
    : path.join(process.cwd(), process.env.SESSIONS_FILE_PATH)  // Relative to current working directory
  : defaultSessionsPath;  // Default fallback

// Software Development specific entity types
const VALID_ENTITY_TYPES = [
  'project',       // Overall software project
  'component',     // Module, service, or package within a project
  'feature',       // Specific functionality being developed
  'issue',         // Bug or problem to be fixed
  'task',          // Work item or activity needed for development
  'technology',    // Language, framework, or tool used
  'decision',      // Important technical or architectural decision
  'milestone',     // Key project deadline or phase
  'environment',   // Development, staging, production environments
  'documentation', // Project documentation
  'requirement',   // Project requirement or specification
  'status',        // Entity status (inactive, active, or complete)
  'priority'       // Entity priority (low or high)
];

// Software Development specific relation types
const VALID_RELATION_TYPES = [
  'depends_on',     // Dependency relationship
  'implements',     // Component implements a feature
  'blocked_by',     // Task is blocked by an issue
  'uses',           // Component uses a technology
  'part_of',        // Component is part of a project
  'contains',       // Project contains a component
  'related_to',     // General relationship
  'affects',        // Issue affects a component
  'resolves',       // Task resolves an issue
  'documented_in',  // Component is documented in documentation
  'decided_in',     // Decision was made in a meeting
  'required_by',    // Feature is required by a requirement
  'has_status',     // Entity has a particular status
  'has_priority',   // Entity has a particular priority
  'depends_on_milestone', // Task depends on reaching a milestone
  'precedes',       // Task precedes another task (for sequencing)
  'tested_in'       // Component is tested in an environment
];

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Collect tool descriptions from text files
const toolDescriptions: Record<string, string> = {
  'startsession': '',
  'loadcontext': '',
  'deletecontext': '',
  'buildcontext': '',
  'advancedcontext': '',
  'endsession': '',
};
for (const tool of Object.keys(toolDescriptions)) {
  try {
    const descriptionFilePath = path.resolve(
      __dirname,
      `developer_${tool}.txt`
    );
    if (existsSync(descriptionFilePath)) {
        toolDescriptions[tool] = readFileSync(descriptionFilePath, 'utf-8');
      }
  } catch (error) {
    console.error(`Error reading description file for tool '${tool}': ${error}`);
  }
}

// Session management functions
async function loadSessionStates(): Promise<Map<string, any[]>> {
  try {
    const fileContent = await fs.readFile(SESSIONS_FILE_PATH, 'utf-8');
    const sessions = JSON.parse(fileContent);
    // Convert from object to Map
    const sessionsMap = new Map<string, any[]>();
    for (const [key, value] of Object.entries(sessions)) {
      sessionsMap.set(key, value as any[]);
    }
    return sessionsMap;
  } catch (error) {
    if (error instanceof Error && 'code' in error && (error as any).code === "ENOENT") {
      return new Map<string, any[]>();
    }
    throw error;
  }
}

async function saveSessionStates(sessionsMap: Map<string, any[]>): Promise<void> {
  // Convert from Map to object
  const sessions: Record<string, any[]> = {};
  for (const [key, value] of sessionsMap.entries()) {
    sessions[key] = value;
  }
  await fs.writeFile(SESSIONS_FILE_PATH, JSON.stringify(sessions, null, 2), 'utf-8');
}

// Generate a unique session ID
function generateSessionId(): string {
  return `dev_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
}

// Basic validation functions
function validateEntityType(entityType: string): boolean {
  return VALID_ENTITY_TYPES.includes(entityType);
}

function validateRelationType(relationType: string): boolean {
  return VALID_RELATION_TYPES.includes(relationType);
}

// We are storing our memory using entities, relations, and observations in a graph structure
interface Entity {
  name: string;
  entityType: string;
  observations: string[];
}

interface Relation {
  from: string;
  to: string;
  relationType: string;
}

interface KnowledgeGraph {
  entities: Entity[];
  relations: Relation[];
}

// Define the valid status and priority values
const VALID_STATUS_VALUES = ['inactive', 'active', 'complete'];
const VALID_PRIORITY_VALUES = ['low', 'high'];

// The KnowledgeGraphManager class contains all operations to interact with the knowledge graph
class KnowledgeGraphManager {
  private async loadGraph(): Promise<KnowledgeGraph> {
    try {
      const fileContent = await fs.readFile(MEMORY_FILE_PATH, 'utf-8');
      return JSON.parse(fileContent);
    } catch (error) {
      if (error instanceof Error && 'code' in error && (error as any).code === "ENOENT") {
        return { entities: [], relations: [] };
      }
      throw error;
    }
  }

  private async saveGraph(graph: KnowledgeGraph): Promise<void> {
    await fs.writeFile(MEMORY_FILE_PATH, JSON.stringify(graph, null, 2), 'utf-8');
  }

  // Initialize status and priority entities
  async initializeStatusAndPriority(): Promise<void> {
    const graph = await this.loadGraph();
    
    // Create status entities if they don't exist
    for (const statusValue of VALID_STATUS_VALUES) {
      const statusName = `status:${statusValue}`;
      if (!graph.entities.some(e => e.name === statusName && e.entityType === 'status')) {
        graph.entities.push({
          name: statusName,
          entityType: 'status',
          observations: [`A ${statusValue} status value`]
        });
      }
    }
    
    // Create priority entities if they don't exist
    for (const priorityValue of VALID_PRIORITY_VALUES) {
      const priorityName = `priority:${priorityValue}`;
      if (!graph.entities.some(e => e.name === priorityName && e.entityType === 'priority')) {
        graph.entities.push({
          name: priorityName,
          entityType: 'priority',
          observations: [`A ${priorityValue} priority value`]
        });
      }
    }
    
    await this.saveGraph(graph);
  }

  // Helper method to get status of an entity
  async getEntityStatus(entityName: string): Promise<string | null> {
    const graph = await this.loadGraph();
    
    // Find status relation for this entity
    const statusRelation = graph.relations.find(r => 
      r.from === entityName && 
      r.relationType === 'has_status'
    );
    
    if (statusRelation) {
      // Extract status value from the status entity name (status:value)
      return statusRelation.to.split(':')[1];
    }
    
    return null;
  }
  
  // Helper method to get priority of an entity
  async getEntityPriority(entityName: string): Promise<string | null> {
    const graph = await this.loadGraph();
    
    // Find priority relation for this entity
    const priorityRelation = graph.relations.find(r => 
      r.from === entityName && 
      r.relationType === 'has_priority'
    );
    
    if (priorityRelation) {
      // Extract priority value from the priority entity name (priority:value)
      return priorityRelation.to.split(':')[1];
    }
    
    return null;
  }
  
  // Helper method to set status of an entity
  async setEntityStatus(entityName: string, statusValue: string): Promise<void> {
    if (!VALID_STATUS_VALUES.includes(statusValue)) {
      throw new Error(`Invalid status value: ${statusValue}. Valid values are: ${VALID_STATUS_VALUES.join(', ')}`);
    }
    
    const graph = await this.loadGraph();
    
    // Remove any existing status relations for this entity
    graph.relations = graph.relations.filter(r => 
      !(r.from === entityName && r.relationType === 'has_status')
    );
    
    // Add new status relation
    graph.relations.push({
      from: entityName,
      to: `status:${statusValue}`,
      relationType: 'has_status'
    });
    
    await this.saveGraph(graph);
  }
  
  // Helper method to set priority of an entity
  async setEntityPriority(entityName: string, priorityValue: string): Promise<void> {
    if (!VALID_PRIORITY_VALUES.includes(priorityValue)) {
      throw new Error(`Invalid priority value: ${priorityValue}. Valid values are: ${VALID_PRIORITY_VALUES.join(', ')}`);
    }
    
    const graph = await this.loadGraph();
    
    // Remove any existing priority relations for this entity
    graph.relations = graph.relations.filter(r => 
      !(r.from === entityName && r.relationType === 'has_priority')
    );
    
    // Add new priority relation
    graph.relations.push({
      from: entityName,
      to: `priority:${priorityValue}`,
      relationType: 'has_priority'
    });
    
    await this.saveGraph(graph);
  }

  async createEntities(entities: Entity[]): Promise<Entity[]> {
    // Validate entity types
    for (const entity of entities) {
      if (!validateEntityType(entity.entityType)) {
        throw new Error(`Invalid entity type: ${entity.entityType}. Valid types are: ${VALID_ENTITY_TYPES.join(', ')}`);
      }
    }

    const graph = await this.loadGraph();
    const newEntities = entities.filter(e => !graph.entities.some(existingEntity => existingEntity.name === e.name));
    graph.entities.push(...newEntities);
    await this.saveGraph(graph);
    return newEntities;
  }

  async createRelations(relations: Relation[]): Promise<Relation[]> {
    // Validate relation types
    for (const relation of relations) {
      if (!validateRelationType(relation.relationType)) {
        throw new Error(`Invalid relation type: ${relation.relationType}. Valid types are: ${VALID_RELATION_TYPES.join(', ')}`);
      }
    }

    const graph = await this.loadGraph();
    
    // Check if entities exist
    for (const relation of relations) {
      const fromEntity = graph.entities.find(e => e.name === relation.from);
      const toEntity = graph.entities.find(e => e.name === relation.to);
      
      if (!fromEntity) {
        throw new Error(`Source entity '${relation.from}' does not exist. Please create it first.`);
      }
      if (!toEntity) {
        throw new Error(`Target entity '${relation.to}' does not exist. Please create it first.`);
      }
    }
    
    const newRelations = relations.filter(r => !graph.relations.some(existingRelation => 
      existingRelation.from === r.from && 
      existingRelation.to === r.to && 
      existingRelation.relationType === r.relationType
    ));
    graph.relations.push(...newRelations);
    await this.saveGraph(graph);
    return newRelations;
  }

  async addObservations(observations: { entityName: string; contents: string[] }[]): Promise<{ entityName: string; addedObservations: string[] }[]> {
    const graph = await this.loadGraph();
    const results = observations.map(o => {
      const entity = graph.entities.find(e => e.name === o.entityName);
      if (!entity) {
        throw new Error(`Entity with name ${o.entityName} not found`);
      }
      const newObservations = o.contents.filter(content => !entity.observations.includes(content));
      entity.observations.push(...newObservations);
      return { entityName: o.entityName, addedObservations: newObservations };
    });
    await this.saveGraph(graph);
    return results;
  }

  async deleteEntities(entityNames: string[]): Promise<void> {
    const graph = await this.loadGraph();
    graph.entities = graph.entities.filter(e => !entityNames.includes(e.name));
    graph.relations = graph.relations.filter(r => !entityNames.includes(r.from) && !entityNames.includes(r.to));
    await this.saveGraph(graph);
  }

  async deleteObservations(deletions: { entityName: string; observations: string[] }[]): Promise<void> {
    const graph = await this.loadGraph();
    deletions.forEach(d => {
      const entity = graph.entities.find(e => e.name === d.entityName);
      if (entity) {
        entity.observations = entity.observations.filter(o => !d.observations.includes(o));
      }
    });
    await this.saveGraph(graph);
  }

  async deleteRelations(relations: Relation[]): Promise<void> {
    const graph = await this.loadGraph();
    graph.relations = graph.relations.filter(r => !relations.some(delRelation => 
      r.from === delRelation.from && 
      r.to === delRelation.to && 
      r.relationType === delRelation.relationType
    ));
    await this.saveGraph(graph);
  }

  async readGraph(): Promise<KnowledgeGraph> {
    return this.loadGraph();
  }

  // Basic search function
  async searchNodes(query: string): Promise<KnowledgeGraph> {
    const graph = await this.loadGraph();
    
    // Filter entities
    const filteredEntities = graph.entities.filter(e => 
      e.name.toLowerCase().includes(query.toLowerCase()) ||
      e.entityType.toLowerCase().includes(query.toLowerCase()) ||
      e.observations.some(o => o.toLowerCase().includes(query.toLowerCase()))
    );
  
    // Create a Set of filtered entity names for quick lookup
    const filteredEntityNames = new Set(filteredEntities.map(e => e.name));
  
    // Filter relations to only include those between filtered entities
    const filteredRelations = graph.relations.filter(r => 
      filteredEntityNames.has(r.from) && filteredEntityNames.has(r.to)
    );
  
    const filteredGraph: KnowledgeGraph = {
      entities: filteredEntities,
      relations: filteredRelations,
    };
  
    return filteredGraph;
  }

  async openNodes(names: string[]): Promise<KnowledgeGraph> {
    const graph = await this.loadGraph();
    
    // Filter entities
    const filteredEntities = graph.entities.filter(e => names.includes(e.name));
  
    // Create a Set of filtered entity names for quick lookup
    const filteredEntityNames = new Set(filteredEntities.map(e => e.name));
  
    // Filter relations to only include those between filtered entities
    const filteredRelations = graph.relations.filter(r => 
      filteredEntityNames.has(r.from) && filteredEntityNames.has(r.to)
    );
  
    const filteredGraph: KnowledgeGraph = {
      entities: filteredEntities,
      relations: filteredRelations,
    };
  
    return filteredGraph;
  }

  // Software Development specific functions
  
  // Get project overview including components, features, issues, etc.
  async getProjectStatus(projectName: string): Promise<any> {
    const graph = await this.loadGraph();
    
    // Find the project entity
    const project = graph.entities.find(e => e.name === projectName && e.entityType === 'project');
    if (!project) {
      throw new Error(`Project '${projectName}' not found`);
    }
    
    // Find components that are part of this project
    const components: Entity[] = [];
    
    // Find features, issues, tasks, milestones related to this project
    const features: Entity[] = [];
    const issues: Entity[] = [];
    const tasks: Entity[] = [];
    const milestones: Entity[] = [];
    
    // Find entities directly related to the project
    for (const relation of graph.relations) {
      if (relation.from === projectName || relation.to === projectName) {
        const relatedEntity = graph.entities.find(e => 
          (relation.from === projectName && e.name === relation.to) || 
          (relation.to === projectName && e.name === relation.from)
        );
        
        if (relatedEntity) {
          if (relatedEntity.entityType === 'component') components.push(relatedEntity);
          if (relatedEntity.entityType === 'feature') features.push(relatedEntity);
          if (relatedEntity.entityType === 'issue') issues.push(relatedEntity);
          if (relatedEntity.entityType === 'task') tasks.push(relatedEntity);
          if (relatedEntity.entityType === 'milestone') milestones.push(relatedEntity);
        }
      }
    }
    
    // Find entities related to components of the project
    for (const component of components) {
      for (const relation of graph.relations) {
        if (relation.from === component.name || relation.to === component.name) {
          const relatedEntity = graph.entities.find(e => 
            (relation.from === component.name && e.name === relation.to) || 
            (relation.to === component.name && e.name === relation.from)
          );
          
          if (relatedEntity) {
            if (relatedEntity.entityType === 'feature' && !features.some(f => f.name === relatedEntity.name)) {
              features.push(relatedEntity);
            }
            if (relatedEntity.entityType === 'issue' && !issues.some(i => i.name === relatedEntity.name)) {
              issues.push(relatedEntity);
            }
            if (relatedEntity.entityType === 'task' && !tasks.some(t => t.name === relatedEntity.name)) {
              tasks.push(relatedEntity);
            }
          }
        }
      }
    }
    
    // Get active tasks and issues
    const statuses: Record<string, string> = {};
    const priorities: Record<string, string> = {};
    
    // Load status and priority for tasks and issues
    for (const entity of [...tasks, ...issues, ...features, ...milestones]) {
      const status = await this.getEntityStatus(entity.name);
      if (status) {
        statuses[entity.name] = status;
      }
      
      const priority = await this.getEntityPriority(entity.name);
      if (priority) {
        priorities[entity.name] = priority;
      }
    }
    
    // Filter active tasks and issues based on status
    const activeTasks = tasks.filter(task => {
      const status = statuses[task.name];
      return status ? status === 'active' : true;
    });
    
    const activeIssues = issues.filter(issue => {
      const status = statuses[issue.name];
      return status ? status === 'active' : true;
    });
    
    // Find upcoming milestones
    const upcomingMilestones = milestones.filter(milestone => {
      const status = statuses[milestone.name];
      return status ? status === 'active' : true;
    });
    
    // Get decision history
    const decisions = graph.entities.filter(e => 
      e.entityType === 'decision' && 
      graph.relations.some(r => 
        (r.from === e.name && r.to === projectName) || 
        (r.to === e.name && r.from === projectName)
      )
    );
    
    // Find task sequencing
    const taskSequencing: Record<string, string[]> = {};
    for (const task of tasks) {
      const precedingTasks: string[] = [];
      const followingTasks: string[] = [];
      
      // Find tasks that this task precedes
      for (const relation of graph.relations) {
        if (relation.from === task.name && relation.relationType === 'precedes') {
          followingTasks.push(relation.to);
        }
        if (relation.to === task.name && relation.relationType === 'precedes') {
          precedingTasks.push(relation.from);
        }
      }
      
      if (precedingTasks.length > 0 || followingTasks.length > 0) {
        taskSequencing[task.name] = {
          precedingTasks,
          followingTasks
        } as any;
      }
    }
    
    return {
      project,
      components,
      activeFeatures: features.filter(f => {
        const status = statuses[f.name];
        return status ? status === 'active' : true;
      }),
      activeTasks,
      activeIssues,
      upcomingMilestones,
      allFeatures: features,
      allIssues: issues,
      allTasks: tasks,
      allMilestones: milestones,
      recentDecisions: decisions.slice(0, 5),  // Limit to 5 most recent decisions
      statuses,  // Include status mapping for reference
      priorities,  // Include priority mapping for reference
      taskSequencing  // Include task sequencing information
    };
  }
  
  // Get detailed context for a specific component
  async getComponentContext(componentName: string): Promise<any> {
    const graph = await this.loadGraph();
    
    // Find the component entity
    const component = graph.entities.find(e => e.name === componentName && e.entityType === 'component');
    if (!component) {
      throw new Error(`Component '${componentName}' not found`);
    }
    
    // Find projects this component is part of
    const projects: Entity[] = [];
    
    for (const relation of graph.relations) {
      if (relation.relationType === 'contains' && relation.to === componentName) {
        const project = graph.entities.find(e => e.name === relation.from && e.entityType === 'project');
        if (project) {
          projects.push(project);
        }
      }
    }
    
    // Find features implemented by this component
    const features: Entity[] = [];
    
    for (const relation of graph.relations) {
      if (relation.relationType === 'implements' && relation.from === componentName) {
        const feature = graph.entities.find(e => e.name === relation.to && e.entityType === 'feature');
        if (feature) {
          features.push(feature);
        }
      }
    }
    
    // Find technologies used by this component
    const technologies: Entity[] = [];
    
    for (const relation of graph.relations) {
      if (relation.relationType === 'uses' && relation.from === componentName) {
        const technology = graph.entities.find(e => e.name === relation.to && e.entityType === 'technology');
        if (technology) {
          technologies.push(technology);
        }
      }
    }
    
    // Find issues affecting this component
    const issues: Entity[] = [];
    
    for (const relation of graph.relations) {
      if (relation.relationType === 'affects' && relation.to === componentName) {
        const issue = graph.entities.find(e => e.name === relation.from && e.entityType === 'issue');
        if (issue) {
          issues.push(issue);
        }
      }
    }
    
    // Find tasks related to this component
    const tasks = [];
    for (const relation of graph.relations) {
      if ((relation.from === componentName || relation.to === componentName) && 
          graph.entities.some(e => 
            (e.name === relation.from || e.name === relation.to) && 
            e.name !== componentName && 
            e.entityType === 'task'
          )) {
        const task = graph.entities.find(e => 
          (e.name === relation.from || e.name === relation.to) && 
          e.name !== componentName && 
          e.entityType === 'task'
        );
        if (task) {
          tasks.push(task);
        }
      }
    }
    
    // Find documentation for this component
    const documentation = [];
    for (const relation of graph.relations) {
      if (relation.relationType === 'documented_in' && relation.from === componentName) {
        const doc = graph.entities.find(e => e.name === relation.to && e.entityType === 'documentation');
        if (doc) {
          documentation.push(doc);
        }
      }
    }
    
    // Find dependencies
    const dependencies = [];
    for (const relation of graph.relations) {
      if (relation.relationType === 'depends_on' && relation.from === componentName) {
        const dependency = graph.entities.find(e => e.name === relation.to);
        if (dependency) {
          dependencies.push(dependency);
        }
      }
    }
    
    // Get statuses and priorities for tasks and issues
    const statuses: Record<string, string> = {};
    const priorities: Record<string, string> = {};
    
    // Load status and priority for tasks and issues
    for (const entity of [...tasks, ...issues, ...features]) {
      const status = await this.getEntityStatus(entity.name);
      if (status) {
        statuses[entity.name] = status;
      }
      
      const priority = await this.getEntityPriority(entity.name);
      if (priority) {
        priorities[entity.name] = priority;
      }
    }
    
    return {
      component,
      projects,
      features,
      technologies,
      activeIssues: issues.filter(issue => {
        const status = statuses[issue.name];
        return status ? status === 'active' : true;
      }),
      activeTasks: tasks.filter(task => {
        const status = statuses[task.name];
        return status ? status === 'active' : true;
      }),
      documentation,
      dependencies,
      allIssues: issues,
      allTasks: tasks,
      statuses,
      priorities
    };
  }
  
  // Get all entities related to a specific entity
  async getRelatedEntities(entityName: string, relationTypes?: string[]): Promise<any> {
    const graph = await this.loadGraph();
    
    // Find the entity
    const entity = graph.entities.find(e => e.name === entityName);
    if (!entity) {
      throw new Error(`Entity '${entityName}' not found`);
    }
    
    // Find all relations involving this entity
    let relevantRelations = graph.relations.filter(r => r.from === entityName || r.to === entityName);
    
    // Filter by relation types if specified
    if (relationTypes && relationTypes.length > 0) {
      relevantRelations = relevantRelations.filter(r => relationTypes.includes(r.relationType));
    }
    
    // Get all related entities
    const related = {
      entity,
      incomingRelations: [] as { relation: Relation; source: Entity }[],
      outgoingRelations: [] as { relation: Relation; target: Entity }[],
    };
    
    for (const relation of relevantRelations) {
      if (relation.from === entityName) {
        const target = graph.entities.find(e => e.name === relation.to);
        if (target) {
          related.outgoingRelations.push({
            relation,
            target
          });
        }
      } else {
        const source = graph.entities.find(e => e.name === relation.from);
        if (source) {
          related.incomingRelations.push({
            relation,
            source
          });
        }
      }
    }
    
    return related;
  }
  
  // Get the history of decisions related to a project
  async getDecisionHistory(projectName: string): Promise<any> {
    const graph = await this.loadGraph();
    
    // Find the project
    const project = graph.entities.find(e => e.name === projectName && e.entityType === "project");
    if (!project) {
      throw new Error(`Project '${projectName}' not found`);
    }
    
    // Find all decision entities related to this project
    const decisions: Entity[] = [];
    
    // Direct decision relations to the project
    for (const relation of graph.relations) {
      if (relation.relationType === "related_to" && relation.to === projectName) {
        const decision = graph.entities.find(e => e.name === relation.from && e.entityType === "decision");
        if (decision) {
          decisions.push(decision);
        }
      }
    }
    
    // Decisions related to components of the project
    const components: Entity[] = [];
    
    for (const relation of graph.relations) {
      if (relation.relationType === "contains" && relation.from === projectName) {
        const component = graph.entities.find(e => e.name === relation.to && e.entityType === "component");
        if (component) {
          components.push(component);
        }
      }
    }
    
    for (const component of components) {
      for (const relation of graph.relations) {
        if (relation.relationType === "related_to" && relation.to === component.name) {
          const decision = graph.entities.find(e => e.name === relation.from && e.entityType === "decision");
          if (decision && !decisions.some(d => d.name === decision.name)) {
            decisions.push(decision);
          }
        }
      }
    }
    
    // Sort decisions chronologically if they have date observations
    const decisionsWithDates = decisions.map(decision => {
      const dateObs = decision.observations.find(o => o.startsWith('Date:'));
      return {
        decision,
        date: dateObs ? new Date(dateObs.split(':')[1].trim()) : new Date(0)
      };
    });
    
    decisionsWithDates.sort((a, b) => b.date.getTime() - a.date.getTime());
    
    return {
      project,
      decisions: decisionsWithDates.map(d => d.decision),
    };
  }
  
  // Get progress toward a milestone
  async getMilestoneProgress(milestoneName: string): Promise<any> {
    const graph = await this.loadGraph();
    
    // Find the milestone
    const milestone = graph.entities.find(e => e.name === milestoneName && e.entityType === "milestone");
    if (!milestone) {
      throw new Error(`Milestone '${milestoneName}' not found`);
    }
    
    // Find all tasks related to this milestone
    const tasks: Entity[] = [];
    
    for (const relation of graph.relations) {
      if (relation.relationType === "related_to" && relation.to === milestoneName) {
        const task = graph.entities.find(e => e.name === relation.from && e.entityType === "task");
        if (task) {
          tasks.push(task);
        }
      }
    }
    
    // Get statuses for all tasks
    const statuses: Record<string, string> = {};
    
    // Load status for tasks
    for (const task of tasks) {
      const status = await this.getEntityStatus(task.name);
      if (status) {
        statuses[task.name] = status;
      }
    }
    
    // Group tasks by status
    const completedTasks: Entity[] = [];
    const inProgressTasks: Entity[] = [];
    const notStartedTasks: Entity[] = [];
    
    for (const task of tasks) {
      const status = statuses[task.name] || 'inactive';
      
      if (status === 'complete') {
        completedTasks.push(task);
      } else if (status === 'active') {
        inProgressTasks.push(task);
      } else {
        notStartedTasks.push(task);
      }
    }
    
    // Calculate progress percentage
    const totalTasks = tasks.length;
    const progressPercentage = totalTasks > 0 
      ? Math.round((completedTasks.length / totalTasks) * 100) 
      : 0;
    
    // Find task sequencing
    const taskSequencing: Record<string, any> = {};
    for (const task of tasks) {
      const precedingTasks: string[] = [];
      const followingTasks: string[] = [];
      
      // Find tasks that this task precedes
      for (const relation of graph.relations) {
        if (relation.from === task.name && relation.relationType === 'precedes') {
          followingTasks.push(relation.to);
        }
        if (relation.to === task.name && relation.relationType === 'precedes') {
          precedingTasks.push(relation.from);
        }
      }
      
      if (precedingTasks.length > 0 || followingTasks.length > 0) {
        taskSequencing[task.name] = {
          precedingTasks,
          followingTasks
        };
      }
    }
    
    // Determine if milestone can be considered complete
    const milestoneComplete = tasks.length > 0 && tasks.every(task => 
      statuses[task.name] === 'complete'
    );
    
    return {
      milestone,
      progress: {
        totalTasks,
        completedTasks: completedTasks.length,
        inProgressTasks: inProgressTasks.length,
        notStartedTasks: notStartedTasks.length,
        percentage: progressPercentage,
        complete: milestoneComplete
      },
      tasks: {
        completed: completedTasks,
        inProgress: inProgressTasks,
        notStarted: notStartedTasks
      },
      taskSequencing,
      statuses
    };
  }
}

// Main function to set up the MCP server
async function main() {
  try {
    const knowledgeGraphManager = new KnowledgeGraphManager();
    
    // Initialize status and priority entities
    await knowledgeGraphManager.initializeStatusAndPriority();
    
    // Initialize session states from persistent storage
    const sessionStates = await loadSessionStates();
    
    // Create the MCP server with a name and version
    const server = new McpServer({
      name: "Context Manager",
      version: "1.0.0"
    });
    
    // Define a resource that exposes the entire graph
    server.resource(
      "graph",
      "graph://developer",
      async (uri) => ({
        contents: [{
          uri: uri.href,
          text: JSON.stringify(await knowledgeGraphManager.readGraph(), null, 2)
        }]
      })
    );
    
    // Define tools using zod for parameter validation
    
    // CRUD operations - these are now consolidated into buildcontext, deletecontext, and advancedcontext tools

    /**
     * Create new entities, relations, and observations.
     */
    server.tool(
      "buildcontext",
      toolDescriptions["buildcontext"],
      {
        type: z.enum(["entities", "relations", "observations"]).describe("Type of creation operation: 'entities', 'relations', or 'observations'"),
        data: z.array(z.any()).describe("Data for the creation operation, structure varies by type but must be an array")
      },
      async ({ type, data }) => {
        try {
          let result;
          
          switch (type) {
            case "entities":
              // Ensure entities match the Entity interface
              const typedEntities: Entity[] = data.map((e: any) => ({
                name: e.name,
                entityType: e.entityType,
                observations: e.observations
              }));
              result = await knowledgeGraphManager.createEntities(typedEntities);
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({ success: true, created: result }, null, 2)
                }]
              };
              
            case "relations":
              // Ensure relations match the Relation interface
              const typedRelations: Relation[] = data.map((r: any) => ({
                from: r.from,
                to: r.to,
                relationType: r.relationType
              }));
              result = await knowledgeGraphManager.createRelations(typedRelations);
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({ success: true, created: result }, null, 2)
                }]
              };
              
            case "observations":
              // Ensure observations match the required interface
              const typedObservations: { entityName: string; contents: string[] }[] = data.map((o: any) => ({
                entityName: o.entityName,
                contents: o.contents
              }));
              result = await knowledgeGraphManager.addObservations(typedObservations);
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({ success: true, added: result }, null, 2)
                }]
              };
              
            default:
              throw new Error(`Invalid type: ${type}. Must be 'entities', 'relations', or 'observations'.`);
          }
        } catch (error) {
          return {
            content: [{
              type: "text",
              text: JSON.stringify({ 
                success: false,
                error: error instanceof Error ? error.message : String(error)
              }, null, 2)
            }]
          };
        }
      }
    );

    /**
     * Delete entities, relations, and observations.
     */
    server.tool(
      "deletecontext",
      toolDescriptions["deletecontext"],
      {
        type: z.enum(["entities", "relations", "observations"]).describe("Type of deletion operation: 'entities', 'relations', or 'observations'"),
        data: z.array(z.any()).describe("Data for the deletion operation, structure varies by type but must be an array")
      },
      async ({ type, data }) => {
        try {
          switch (type) {
            case "entities":
              await knowledgeGraphManager.deleteEntities(data);
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({ success: true, message: `Deleted ${data.length} entities` }, null, 2)
                }]
              };
              
            case "relations":
              // Ensure relations match the Relation interface
              const typedRelations: Relation[] = data.map((r: any) => ({
                from: r.from,
                to: r.to,
                relationType: r.relationType
              }));
              await knowledgeGraphManager.deleteRelations(typedRelations);
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({ success: true, message: `Deleted ${data.length} relations` }, null, 2)
                }]
              };
              
            case "observations":
              // Ensure deletions match the required interface
              const typedDeletions: { entityName: string; observations: string[] }[] = data.map((d: any) => ({
                entityName: d.entityName,
                observations: d.observations
              }));
              await knowledgeGraphManager.deleteObservations(typedDeletions);
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({ success: true, message: `Deleted observations from ${data.length} entities` }, null, 2)
                }]
              };
              
            default:
              throw new Error(`Invalid type: ${type}. Must be 'entities', 'relations', or 'observations'.`);
          }
        } catch (error) {
          return {
            content: [{
              type: "text",
              text: JSON.stringify({ 
                success: false,
                error: error instanceof Error ? error.message : String(error)
              }, null, 2)
            }]
          };
        }
      }
    );

    /**
     * Get information about the graph, search for nodes, open nodes, get related entities, get decision history, and get milestone progress.
     */
    server.tool(
      "advancedcontext",
      toolDescriptions["advancedcontext"],
      {
        type: z.enum(["graph", "search", "nodes", "related", "decisions", "milestone"]).describe("Type of get operation: 'graph', 'search', 'nodes', 'related', 'decisions', or 'milestone'"),
        params: z.record(z.string(), z.any()).describe("Parameters for the operation, structure varies by type")
      },
      async ({ type, params }) => {
        try {
          let result;
          
          switch (type) {
            case "graph":
              result = await knowledgeGraphManager.readGraph();
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({ success: true, graph: result }, null, 2)
                }]
              };
              
            case "search":
              result = await knowledgeGraphManager.searchNodes(params.query);
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({ success: true, results: result }, null, 2)
                }]
              };
              
            case "nodes":
              result = await knowledgeGraphManager.openNodes(params.names);
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({ success: true, nodes: result }, null, 2)
                }]
              };
              
            case "related":
              result = await knowledgeGraphManager.getRelatedEntities(params.entityName, params.relationTypes);
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({ success: true, entities: result }, null, 2)
                }]
              };
              
            case "decisions":
              result = await knowledgeGraphManager.getDecisionHistory(params.projectName);
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({ success: true, decisions: result }, null, 2)
                }]
              };
              
            case "milestone":
              result = await knowledgeGraphManager.getMilestoneProgress(params.milestoneName);
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({ success: true, progress: result }, null, 2)
                }]
              };
              
            default:
              throw new Error(`Invalid type: ${type}. Must be 'graph', 'search', 'nodes', 'related', 'decisions', or 'milestone'.`);
          }
        } catch (error) {
          return {
            content: [{
              type: "text",
              text: JSON.stringify({ 
                success: false,
                error: error instanceof Error ? error.message : String(error)
              }, null, 2)
            }]
          };
        }
      }
    );

    /**
     * Start a new development session. Returns session ID, recent development sessions, active projects, high-priority tasks, and upcoming milestones.
     * The output allows the user to easily choose what to focus on and which specific context to load.
     */
    server.tool(
      "startsession",
      toolDescriptions["startsession"],
      {},
      async () => {
        try {
          // Generate a unique session ID
          const sessionId = generateSessionId();
          
          // Get recent sessions from persistent storage
          const sessionStates = await loadSessionStates();

          // Initialize the session state
          sessionStates.set(sessionId, []);
          await saveSessionStates(sessionStates);
          
          // Convert sessions map to array, sort by date, and take most recent ones
          const recentSessions = Array.from(sessionStates.entries())
            .map(([id, stages]) => {
              // Extract summary data from the first stage (if it exists)
              const summaryStage = stages.find(s => s.stage === "summary");
              return {
                id,
                project: summaryStage?.stageData?.project || "Unknown project",
                focus: summaryStage?.stageData?.focus || "Unknown focus",
                summary: summaryStage?.stageData?.summary || "No summary available"
              };
            })
            .slice(0, 3); // Default to showing 3 recent sessions
          
          // Get active development projects
          const graph = await knowledgeGraphManager.readGraph();
          const activeProjects = [];
          
          // Find projects with active status
          for (const entity of graph.entities) {
            if (entity.entityType === 'project') {
              const status = await knowledgeGraphManager.getEntityStatus(entity.name);
              if (status === 'active') {
                activeProjects.push(entity);
              }
            }
          }
          
          // Get high-priority development tasks
          const highPriorityTasks = [];
          
          // Find tasks with high priority and active status
          for (const entity of graph.entities) {
            if (entity.entityType === 'task') {
              const status = await knowledgeGraphManager.getEntityStatus(entity.name);
              const priority = await knowledgeGraphManager.getEntityPriority(entity.name);
              
              if (status === 'active' && priority === 'high') {
                highPriorityTasks.push(entity);
              }
            }
          }
          
          // Get upcoming milestones
          const upcomingMilestones = [];
          
          // Find milestones with active status
          for (const entity of graph.entities) {
            if (entity.entityType === 'milestone') {
              const status = await knowledgeGraphManager.getEntityStatus(entity.name);
              
              if (status === 'active') {
                upcomingMilestones.push(entity);
              }
            }
          }
          
          let sessionsText = "No recent sessions found.";
          if (recentSessions.length > 0) {
            sessionsText = recentSessions.map(session => 
              `- ${session.project} - ${session.focus} - ${session.summary.substring(0, 100)}${session.summary.length > 100 ? '...' : ''}`
            ).join('\n');
          }
          
          let projectsText = "No active projects found.";
          if (activeProjects.length > 0) {
            projectsText = activeProjects.map(project => {
              const obsPreview = project.observations.length > 0 ? 
                `: ${project.observations[0].substring(0, 60)}${project.observations[0].length > 60 ? '...' : ''}` : '';
              return `- ${project.name}${obsPreview}`;
            }).join('\n');
          }
          
          let tasksText = "No high-priority tasks found.";
          if (highPriorityTasks.length > 0) {
            tasksText = highPriorityTasks.map(task => {
              const obsPreview = task.observations.length > 0 ? 
                `: ${task.observations[0].substring(0, 60)}${task.observations[0].length > 60 ? '...' : ''}` : '';
              return `- ${task.name}${obsPreview}`;
            }).join('\n');
          }
          
          let milestonesText = "No upcoming milestones found.";
          if (upcomingMilestones.length > 0) {
            milestonesText = upcomingMilestones.map(milestone => {
              const obsPreview = milestone.observations.length > 0 ? 
                `: ${milestone.observations[0].substring(0, 60)}${milestone.observations[0].length > 60 ? '...' : ''}` : '';
              return `- ${milestone.name}${obsPreview}`;
            }).join('\n');
          }
          
          return {
            content: [{
              type: "text",
              text: `# Ask user to choose what to focus on in this session. Present the following options:

## Recent Development Sessions
${sessionsText}

## Active Projects
${projectsText}

## High-Priority Tasks
${tasksText}

## Upcoming Milestones
${milestonesText}

To load specific context based on the user's choice, use the \`loadcontext\` tool with the entity name and developer session ID - ${sessionId}.`
            }]
          };
        } catch (error) {
          return {
            content: [{
              type: "text",
              text: JSON.stringify({ 
                success: false,
                error: error instanceof Error ? error.message : String(error)
              }, null, 2)
            }]
          };
        }
      }
    );

    /**
     * Load the context for a specific entity.
     * Valid entity types are: project, component, task, issue, milestone, decision, feature, technology, documentation, dependency.
     */
    server.tool(
      "loadcontext",
      toolDescriptions["loadcontext"],
      {
        entityName: z.string(),
        entityType: z.string().optional(),
        sessionId: z.string().optional() 
      },
      async ({ entityName, entityType = "project", sessionId }) => {
        try {
          // Validate session if ID is provided
          if (sessionId) {
            const sessionStates = await loadSessionStates();
            if (!sessionStates.has(sessionId)) {
              console.warn(`Warning: Session ${sessionId} not found, but proceeding with context load`);
              // Initialize it anyway for more robustness
              sessionStates.set(sessionId, []);
              await saveSessionStates(sessionStates);
            }
            
            // Track that this entity was loaded in this session
            const sessionState = sessionStates.get(sessionId) || [];
            const loadEvent = {
              type: 'context_loaded',
              timestamp: new Date().toISOString(),
              entityName,
              entityType
            };
            sessionState.push(loadEvent);
            sessionStates.set(sessionId, sessionState);
            await saveSessionStates(sessionStates);
          }
          
          // Get entity
          const entityGraph = await knowledgeGraphManager.searchNodes(entityName);
          if (entityGraph.entities.length === 0) {
            throw new Error(`Entity ${entityName} not found`);
          }
          
          // Find the exact entity by name (case-sensitive match)
          const entity = entityGraph.entities.find(e => e.name === entityName);
          if (!entity) {
            throw new Error(`Entity ${entityName} not found`);
          }
          
          // Get status and priority
          const status = await knowledgeGraphManager.getEntityStatus(entityName) || "unknown";
          const priority = await knowledgeGraphManager.getEntityPriority(entityName);
          
          // Format observations for display (show all observations)
          const observationsList = entity.observations.length > 0 
            ? entity.observations.map(obs => `- ${obs}`).join("\n")
            : "No observations";
          
          // Different context loading based on entity type
          let contextMessage = "";
          
          if (entityType === "project") {
            // Get project status
            const projectStatus = await knowledgeGraphManager.getProjectStatus(entityName);
            
            // Format project context
            const componentsText = projectStatus.components?.map((component: Entity) => {
              return `- **${component.name}**${component.observations.length > 0 ? `: ${component.observations[0]}` : ''}`;
            }).join("\n") || "No components found";
            
            const featuresText = projectStatus.activeFeatures?.map((feature: Entity) => {
              const featureStatus = projectStatus.statuses[feature.name] || "unknown";
              return `- **${feature.name}** (${featureStatus})${feature.observations.length > 0 ? `: ${feature.observations.join(', ')}` : ''}`;
            }).join("\n") || "No active features found";
            
            const tasksText = projectStatus.activeTasks?.map((task: Entity) => {
              const taskStatus = projectStatus.statuses[task.name] || "unknown";
              const taskPriority = projectStatus.priorities[task.name] || "normal";
              return `- **${task.name}** (${taskStatus}, ${taskPriority} priority)${task.observations.length > 0 ? `: ${task.observations.join(', ')}` : ''}`;
            }).join("\n") || "No active tasks found";
            
            const issuesText = projectStatus.activeIssues?.map((issue: Entity) => {
              const issueStatus = projectStatus.statuses[issue.name] || "unknown";
              return `- **${issue.name}** (${issueStatus})${issue.observations.length > 0 ? `: ${issue.observations.join(', ')}` : ''}`;
            }).join("\n") || "No active issues found";
            
            const milestonesText = projectStatus.upcomingMilestones?.map((milestone: Entity) => {
              const milestoneStatus = projectStatus.statuses[milestone.name] || "unknown";
              return `- **${milestone.name}** (${milestoneStatus})${milestone.observations.length > 0 ? `: ${milestone.observations.join(', ')}` : ''}`;
            }).join("\n") || "No upcoming milestones found";
            
            const decisionsText = projectStatus.recentDecisions?.map((decision: Entity) => {
              return `- **${decision.name}**${decision.observations.length > 0 ? `: ${decision.observations.join(', ')}` : ''}`;
            }).join("\n") || "No recent decisions";
            
            // Task sequencing information
            const sequencingText = Object.keys(projectStatus.taskSequencing || {}).length > 0
              ? Object.entries(projectStatus.taskSequencing).map(([taskName, sequence]: [string, any]) => {
                  return `- **${taskName}**:\n  - Precedes: ${sequence.followingTasks.length > 0 ? sequence.followingTasks.join(', ') : 'None'}\n  - Follows: ${sequence.precedingTasks.length > 0 ? sequence.precedingTasks.join(', ') : 'None'}`;
                }).join("\n")
              : "No task sequencing information available";
            
            contextMessage = `# Software Development Project Context: ${entityName}

## Project Overview
- **Status**: ${status}
- **Priority**: ${priority || "N/A"}

## Observations
${observationsList}

## Components
${componentsText}

## Active Features
${featuresText}

## Active Tasks
${tasksText}

## Active Issues
${issuesText}

## Upcoming Milestones
${milestonesText}

## Recent Decisions
${decisionsText}

## Task Sequencing
${sequencingText}`;
          } 
          else if (entityType === "component") {
            // Get component context
            const componentContext = await knowledgeGraphManager.getComponentContext(entityName);
            
            const projectsText = componentContext.projects?.map((project: Entity) => {
              return `- **${project.name}**${project.observations.length > 0 ? `: ${project.observations.join(', ')}` : ''}`;
            }).join("\n") || "No parent projects found";
            
            const featuresText = componentContext.features?.map((feature: Entity) => {
              const featureStatus = componentContext.statuses[feature.name] || "unknown";
              return `- **${feature.name}** (${featureStatus})${feature.observations.length > 0 ? `: ${feature.observations.join(', ')}` : ''}`;
            }).join("\n") || "No implemented features found";
            
            const technologiesText = componentContext.technologies?.map((tech: Entity) => {
              return `- **${tech.name}**${tech.observations.length > 0 ? `: ${tech.observations.join(', ')}` : ''}`;
            }).join("\n") || "No technologies specified";
            
            const issuesText = componentContext.activeIssues?.map((issue: Entity) => {
              const issueStatus = componentContext.statuses[issue.name] || "unknown";
              return `- **${issue.name}** (${issueStatus})${issue.observations.length > 0 ? `: ${issue.observations.join(', ')}` : ''}`;
            }).join("\n") || "No active issues found";
            
            const dependenciesText = componentContext.dependencies?.map((dep: Entity) => {
              return `- **${dep.name}** (${dep.entityType})${dep.observations.length > 0 ? `: ${dep.observations.join(', ')}` : ''}`;
            }).join("\n") || "No dependencies found";
            
            const documentationText = componentContext.documentation?.map((doc: Entity) => {
              return `- **${doc.name}**${doc.observations.length > 0 ? `: ${doc.observations.join(', ')}` : ''}`;
            }).join("\n") || "No documentation found";
            
            contextMessage = `# Component Context: ${entityName}

## Overview
- **Status**: ${status}
- **Priority**: ${priority || "N/A"}

## Observations
${observationsList}

## Part of Projects
${projectsText}

## Technologies
${technologiesText}

## Implemented Features
${featuresText}

## Dependencies
${dependenciesText}

## Active Issues
${issuesText}

## Documentation
${documentationText}`;
          }
          else if (entityType === "feature") {
            // Get related entities
            const relatedEntities = await knowledgeGraphManager.getRelatedEntities(entityName);
            
            // Find implementing components
            const implementingComponents = relatedEntities.incomingRelations
              .filter((rel: { relation: Relation; source: Entity }) => rel.relation.relationType === "implements")
              .map((rel: { relation: Relation; source: Entity }) => rel.source);
            
            const componentsText = implementingComponents.map((component: Entity) => {
              return `- **${component.name}**${component.observations.length > 0 ? `: ${component.observations.join(', ')}` : ''}`;
            }).join("\n") || "No implementing components found";
            
            // Find related tasks
            const relatedTasks = [...relatedEntities.incomingRelations, ...relatedEntities.outgoingRelations]
              .filter((rel: { relation: Relation; source?: Entity; target?: Entity }) => 
                rel.relation.relationType === "related_to" && 
                (rel.source?.entityType === "task" || rel.target?.entityType === "task")
              )
              .map((rel: { relation: Relation; source?: Entity; target?: Entity }) => 
                rel.source?.entityType === "task" ? rel.source : rel.target
              )
              .filter((entity): entity is Entity => entity !== undefined);
            
            // Get status for each task
            const taskStatuses: Record<string, string> = {};
            for (const task of relatedTasks) {
              const taskStatus = await knowledgeGraphManager.getEntityStatus(task.name);
              if (taskStatus) {
                taskStatuses[task.name] = taskStatus;
              }
            }
            
            const tasksText = relatedTasks.map((task: Entity) => {
              const taskStatus = taskStatuses[task.name] || "unknown";
              return `- **${task.name}** (${taskStatus})${task.observations.length > 0 ? `: ${task.observations.join(', ')}` : ''}`;
            }).join("\n") || "No related tasks found";
            
            // Find requirements
            const requirements = relatedEntities.incomingRelations
              .filter((rel: { relation: Relation; source: Entity }) => rel.relation.relationType === "required_by")
              .map((rel: { relation: Relation; source: Entity }) => rel.source);
            
            const requirementsText = requirements.map((req: Entity) => {
              return `- **${req.name}**${req.observations.length > 0 ? `: ${req.observations.join(', ')}` : ''}`;
            }).join("\n") || "No requirements specified";
            
            contextMessage = `# Feature Context: ${entityName}

## Overview
- **Status**: ${status}
- **Priority**: ${priority || "normal"}

## Observations
${observationsList}

## Requirements
${requirementsText}

## Implementing Components
${componentsText}

## Related Tasks
${tasksText}`;
          }
          else if (entityType === "task") {
            // Get related entities
            const relatedEntities = await knowledgeGraphManager.getRelatedEntities(entityName);
            
            // Find related issues
            const relatedIssues = relatedEntities.outgoingRelations
              .filter((rel: { relation: Relation; target: Entity }) => rel.relation.relationType === "resolves")
              .map((rel: { relation: Relation; target: Entity }) => rel.target);
            
            // Get status for each issue
            const issueStatuses: Record<string, string> = {};
            for (const issue of relatedIssues) {
              const issueStatus = await knowledgeGraphManager.getEntityStatus(issue.name);
              if (issueStatus) {
                issueStatuses[issue.name] = issueStatus;
              }
            }
            
            const issuesText = relatedIssues.map((issue: Entity) => {
              const issueStatus = issueStatuses[issue.name] || "unknown";
              return `- **${issue.name}** (${issueStatus})${issue.observations.length > 0 ? `: ${issue.observations.join(', ')}` : ''}`;
            }).join("\n") || "No related issues found";
            
            // Find parent project
            const parentProjects = relatedEntities.incomingRelations
              .filter((rel: { relation: Relation; source: Entity }) => rel.relation.relationType === "contains" && rel.source.entityType === "project")
              .map((rel: { relation: Relation; source: Entity }) => rel.source);
            
            const projectName = parentProjects.length > 0 ? parentProjects[0].name : "Unknown project";
            
            // Find blocking tasks or issues
            const blockingItems = relatedEntities.outgoingRelations
              .filter((rel: { relation: Relation; target: Entity }) => rel.relation.relationType === "blocked_by")
              .map((rel: { relation: Relation; target: Entity }) => rel.target);
            
            // Get status for each blocking item
            const blockingStatuses: Record<string, string> = {};
            for (const item of blockingItems) {
              const itemStatus = await knowledgeGraphManager.getEntityStatus(item.name);
              if (itemStatus) {
                blockingStatuses[item.name] = itemStatus;
              }
            }
            
            const blockingText = blockingItems.map((item: Entity) => {
              const itemStatus = blockingStatuses[item.name] || "unknown";
              return `- **${item.name}** (${item.entityType}, ${itemStatus})${item.observations.length > 0 ? `: ${item.observations.join(', ')}` : ''}`;
            }).join("\n") || "No blocking items";
            
            // Find task sequencing
            const precedingTasks: string[] = [];
            const followingTasks: string[] = [];
            
            // Get the graph to find sequencing relations
            const graph = await knowledgeGraphManager.readGraph();
            
            for (const relation of graph.relations) {
              if (relation.from === entityName && relation.relationType === 'precedes') {
                followingTasks.push(relation.to);
              }
              if (relation.to === entityName && relation.relationType === 'precedes') {
                precedingTasks.push(relation.from);
              }
            }
            
            const sequencingText = `### Preceding Tasks\n${precedingTasks.length > 0 ? precedingTasks.map(t => `- ${t}`).join('\n') : 'None'}\n\n### Following Tasks\n${followingTasks.length > 0 ? followingTasks.map(t => `- ${t}`).join('\n') : 'None'}`;
            
            contextMessage = `# Task Context: ${entityName}

## Overview
- **Project**: ${projectName}
- **Status**: ${status}
- **Priority**: ${priority || "normal"}

## Observations
${observationsList}

## Related Issues
${issuesText}

## Blocked By
${blockingText}

## Task Sequencing
${sequencingText}`;
          }
          else if (entityType === "milestone") {
            // Get milestone progress
            const milestoneProgress = await knowledgeGraphManager.getMilestoneProgress(entityName);
            
            contextMessage = `# Milestone Context: ${entityName}

## Overview
- **Status**: ${status}
- **Progress**: ${milestoneProgress.progress?.percentage || 0}% complete
- **Complete**: ${milestoneProgress.progress?.complete ? "Yes" : "No"}

## Observations
${observationsList}

## Tasks
### Completed (${milestoneProgress.tasks?.completed?.length || 0})
${milestoneProgress.tasks?.completed?.map((task: Entity) => {
  return `- **${task.name}**${task.observations.length > 0 ? `: ${task.observations.join(', ')}` : ''}`;
}).join("\n") || "No completed tasks"}

### In Progress (${milestoneProgress.tasks?.inProgress?.length || 0})
${milestoneProgress.tasks?.inProgress?.map((task: Entity) => {
  return `- **${task.name}**${task.observations.length > 0 ? `: ${task.observations.join(', ')}` : ''}`;
}).join("\n") || "No in-progress tasks"}

### Not Started (${milestoneProgress.tasks?.notStarted?.length || 0})
${milestoneProgress.tasks?.notStarted?.map((task: Entity) => {
  return `- **${task.name}**${task.observations.length > 0 ? `: ${task.observations.join(', ')}` : ''}`;
}).join("\n") || "No not-started tasks"}

## Task Sequencing
${Object.keys(milestoneProgress.taskSequencing || {}).length > 0
  ? Object.entries(milestoneProgress.taskSequencing).map(([taskName, sequence]: [string, any]) => {
      return `- **${taskName}**:\n  - Precedes: ${sequence.followingTasks.length > 0 ? sequence.followingTasks.join(', ') : 'None'}\n  - Follows: ${sequence.precedingTasks.length > 0 ? sequence.precedingTasks.join(', ') : 'None'}`;
    }).join("\n")
  : "No task sequencing information available"}`;
          }
          
          return {
            content: [{
              type: "text",
              text: contextMessage
            }]
          };
        } catch (error) {
          return {
            content: [{
              type: "text",
              text: JSON.stringify({ 
                success: false,
                error: error instanceof Error ? error.message : String(error)
              }, null, 2)
            }]
          };
        }
      }
    );

    // Helper function to process each stage of endsession
    async function processStage(params: {
      sessionId: string;
      stage: string;
      stageNumber: number;
      totalStages: number;
      analysis?: string;
      stageData?: any;
      nextStageNeeded: boolean;
      isRevision?: boolean;
      revisesStage?: number;
    }, previousStages: any[]): Promise<any> {
      // Process based on the stage
      switch (params.stage) {
        case "summary":
          // Process summary stage
          return {
            stage: "summary",
            stageNumber: params.stageNumber,
            analysis: params.analysis || "",
            stageData: params.stageData || { 
              summary: "",
              duration: "",
              focus: ""
            },
            completed: !params.nextStageNeeded
          };
          
        case "achievements":
          // Process achievements stage
          return {
            stage: "achievements",
            stageNumber: params.stageNumber,
            analysis: params.analysis || "",
            stageData: params.stageData || { achievements: [] },
            completed: !params.nextStageNeeded
          };
          
        case "taskUpdates":
          // Process task updates stage
          return {
            stage: "taskUpdates",
            stageNumber: params.stageNumber,
            analysis: params.analysis || "",
            stageData: params.stageData || { taskUpdates: [] },
            completed: !params.nextStageNeeded
          };
          
        case "newTasks":
          // Process new tasks stage
          return {
            stage: "newTasks",
            stageNumber: params.stageNumber,
            analysis: params.analysis || "",
            stageData: params.stageData || { newTasks: [] },
            completed: !params.nextStageNeeded
          };
          
        case "projectStatus":
          // Process project status stage
          return {
            stage: "projectStatus",
            stageNumber: params.stageNumber,
            analysis: params.analysis || "",
            stageData: params.stageData || { 
              projectName: "",
              projectStatus: "",
              projectObservation: ""
            },
            completed: !params.nextStageNeeded
          };
          
        case "assembly":
          // Final assembly stage - compile all arguments for end session
          return {
            stage: "assembly",
            stageNumber: params.stageNumber,
            analysis: "Final assembly of endsession arguments",
            stageData: assembleEndSessionArgs(previousStages),
            completed: true
          };
          
        default:
          throw new Error(`Unknown stage: ${params.stage}`);
      }
    }

    // Helper function to assemble the final end session arguments
    function assembleEndSessionArgs(stages: any[]): any {
      const summaryStage = stages.find(s => s.stage === "summary");
      const achievementsStage = stages.find(s => s.stage === "achievements");
      const taskUpdatesStage = stages.find(s => s.stage === "taskUpdates");
      const newTasksStage = stages.find(s => s.stage === "newTasks");
      const projectStatusStage = stages.find(s => s.stage === "projectStatus");
      
      return {
        summary: summaryStage?.stageData?.summary || "",
        duration: summaryStage?.stageData?.duration || "unknown",
        focus: summaryStage?.stageData?.focus || "",
        achievements: JSON.stringify(achievementsStage?.stageData?.achievements || []),
        taskUpdates: JSON.stringify(taskUpdatesStage?.stageData?.taskUpdates || []),
        projectName: projectStatusStage?.stageData?.projectName || "",
        projectStatus: projectStatusStage?.stageData?.projectStatus || "",
        projectObservation: projectStatusStage?.stageData?.projectObservation || "",
        newTasks: JSON.stringify(newTasksStage?.stageData?.newTasks || [])
      };
    }

    /**
     * End session by processing all stages and recording the final results.
     * Only use this tool if the user asks for it.
     * 
     * Usage examples:
     * 
     * 1. Starting the end session process with the summary stage:
     * {
     *   "sessionId": "dev_1234567890_abc123",  // From startsession
     *   "stage": "summary",
     *   "stageNumber": 1,
     *   "totalStages": 6,  // Total stages you plan to use
     *   "analysis": "Analyzed progress on the authentication system",
     *   "stageData": {
     *     "summary": "Completed the login functionality and fixed related bugs",
     *     "duration": "3 hours",
     *     "focus": "AuthSystem"  // Project/component name
     *   },
     *   "nextStageNeeded": true,  // More stages coming
     *   "isRevision": false
     * }
     * 
     * 2. Middle stage for achievements:
     * {
     *   "sessionId": "dev_1234567890_abc123",
     *   "stage": "achievements",
     *   "stageNumber": 2,
     *   "totalStages": 6,
     *   "analysis": "Listed key accomplishments",
     *   "stageData": {
     *     "achievements": [
     *       "Implemented password reset functionality",
     *       "Fixed login redirect bug",
     *       "Added error handling for authentication failures"
     *     ]
     *   },
     *   "nextStageNeeded": true,
     *   "isRevision": false
     * }
     * 
     * 3. Final assembly stage:
     * {
     *   "sessionId": "dev_1234567890_abc123",
     *   "stage": "assembly",
     *   "stageNumber": 6,
     *   "totalStages": 6,
     *   "nextStageNeeded": false,  // This completes the session
     *   "isRevision": false
     * }
     */
    server.tool(
      "endsession",
      toolDescriptions["endsession"],
      {
        sessionId: z.string().describe("The unique session identifier obtained from startsession"),
        stage: z.string().describe("Current stage of analysis: 'summary', 'achievements', 'taskUpdates', 'newTasks', 'projectStatus', or 'assembly'"),
        stageNumber: z.number().int().positive().describe("The sequence number of the current stage (starts at 1)"),
        totalStages: z.number().int().positive().describe("Total number of stages in the workflow (typically 6 for standard workflow)"),
        analysis: z.string().optional().describe("Text analysis or observations for the current stage"),
        stageData: z.record(z.string(), z.any()).optional().describe(`Stage-specific data structure - format depends on the stage type:
        - For 'summary' stage: { summary: "Session summary text", duration: "2 hours", focus: "ProjectName" }
        - For 'achievements' stage: { achievements: ["Implemented feature X", "Fixed bug Y", "Refactored component Z"] }
        - For 'taskUpdates' stage: { taskUpdates: [{ name: "Task1", status: "completed" }, { name: "Task2", status: "in_progress" }] }
        - For 'newTasks' stage: { newTasks: [{ name: "NewTask1", description: "Implement feature A", priority: "high" }] }
        - For 'projectStatus' stage: { projectName: "ProjectName", projectStatus: "in_progress", projectObservation: "Making good progress" }
        - For 'assembly' stage: no stageData needed - automatic assembly of previous stages`),
        nextStageNeeded: z.boolean().describe("Whether additional stages are needed after this one (false for final stage)"),
        isRevision: z.boolean().optional().describe("Whether this is revising a previous stage"),
        revisesStage: z.number().int().positive().optional().describe("If revising, which stage number is being revised")
      },
      async (params) => {
        try {
          
          // Load session states from persistent storage
          const sessionStates = await loadSessionStates();
          
          // Validate session ID
          if (!sessionStates.has(params.sessionId)) {
            return {
              content: [{
                type: "text",
                text: JSON.stringify({ 
                  success: false,
                  error: `Session with ID ${params.sessionId} not found. Please start a new session with startsession.`
                }, null, 2)
              }]
            };
          }
          
          // Get or initialize session state
          let sessionState = sessionStates.get(params.sessionId) || [];
          
          // Process the current stage
          const stageResult = await processStage(params, sessionState);
          
          // Store updated state
          if (params.isRevision && params.revisesStage) {
            // Find the analysis stages in the session state
            const analysisStages = sessionState.filter(item => item.type === 'analysis_stage') || [];
            
            if (params.revisesStage <= analysisStages.length) {
              // Replace the revised stage
              analysisStages[params.revisesStage - 1] = {
                type: 'analysis_stage',
                ...stageResult
              };
            } else {
              // Add as a new stage
              analysisStages.push({
                type: 'analysis_stage',
                ...stageResult
              });
            }
            
            // Update the session state with the modified analysis stages
            sessionState = [
              ...sessionState.filter(item => item.type !== 'analysis_stage'),
              ...analysisStages
            ];
          } else {
            // Add new stage
            sessionState.push({
              type: 'analysis_stage',
              ...stageResult
            });
          }
          
          // Update in-memory and persistent storage
          sessionStates.set(params.sessionId, sessionState);
          await saveSessionStates(sessionStates);
          
          // Check if this is the final assembly stage and no more stages are needed
          if (params.stage === "assembly" && !params.nextStageNeeded) {
            // Get the assembled arguments
            const args = stageResult.stageData;
            
            try {
              // Parse arguments
              const summary = args.summary;
              const duration = args.duration;
              const focus = args.focus;
              const achievements = args.achievements ? JSON.parse(args.achievements) : [];
              const taskUpdates = args.taskUpdates ? JSON.parse(args.taskUpdates) : [];
              const projectUpdate = {
                name: args.projectName,
                status: args.projectStatus,
                observation: args.projectObservation
              };
              const newTasks = args.newTasks ? JSON.parse(args.newTasks) : [];
              
              // 2. Create achievement entities and link to focus project
              const achievementEntities = achievements.map((achievement: string, i: number) => ({
                name: `Achievement_${new Date().getTime()}_${i + 1}`,
                entityType: "decision",
                observations: [achievement]
              }));
              
              if (achievementEntities.length > 0) {
                await knowledgeGraphManager.createEntities(achievementEntities);
                
                // Link achievements to focus project
                const achievementRelations = achievementEntities.map((achievement: {name: string}) => ({
                  from: focus,
                  to: achievement.name,
                  relationType: "contains"
                }));
                
                await knowledgeGraphManager.createRelations(achievementRelations);
              }
              
              // 3. Update task statuses
              for (const task of taskUpdates) {
                // First find the task entity
                const taskGraph = await knowledgeGraphManager.searchNodes(`name:${task.name}`);
                if (taskGraph.entities.length > 0) {
                  // Update the status observation
                  const taskEntity = taskGraph.entities[0];
                  
                  // Set task status
                  try {
                    const statusValue = task.status === "completed" || task.status === "complete" ? "complete" :
                                       task.status === "in_progress" ? "active" : "inactive";
                    await knowledgeGraphManager.setEntityStatus(task.name, statusValue);
                  } catch (error) {
                    console.error(`Error updating status for task ${task.name}: ${error}`);
                  }
                  
                  // If completed, link to this session
                  if (task.status === "complete" || task.status === "completed") {
                    await knowledgeGraphManager.createRelations([{
                      from: focus,
                      to: task.name,
                      relationType: "resolves"
                    }]);
                  }
                }
              }
              
              // 4. Update project status
              const projectGraph = await knowledgeGraphManager.searchNodes(`name:${projectUpdate.name}`);
              if (projectGraph.entities.length > 0) {
                const projectEntity = projectGraph.entities[0];
                
                // Add project observation if specified
                if (projectUpdate.observation) {
                  await knowledgeGraphManager.addObservations([{
                    entityName: projectUpdate.name,
                    contents: [projectUpdate.observation]
                  }]);
                }
                
                // Set project status
                try {
                  const statusValue = projectUpdate.status === "completed" || projectUpdate.status === "complete" ? "complete" :
                                     projectUpdate.status === "in_progress" || projectUpdate.status === "active" ? "active" : "inactive";
                  await knowledgeGraphManager.setEntityStatus(projectUpdate.name, statusValue);
                } catch (error) {
                  console.error(`Error updating status for project ${projectUpdate.name}: ${error}`);
                }
              }
              
              // 5. Create new tasks
              if (newTasks && newTasks.length > 0) {
                const taskEntities = newTasks.map((task: {name: string, description: string, priority?: string, precedes?: string, follows?: string}, i: number) => ({
                  name: task.name,
                  entityType: "task",
                  observations: [
                    task.description
                  ]
                }));
                
                await knowledgeGraphManager.createEntities(taskEntities);
                
                // Set status, priority, and sequencing for each task
                for (const task of newTasks) {
                  // Set task status to active by default
                  try {
                    await knowledgeGraphManager.setEntityStatus(task.name, "active");
                  } catch (error) {
                    console.error(`Error setting status for new task ${task.name}: ${error}`);
                  }
                  
                  // Set task priority if specified
                  if (task.priority) {
                    try {
                      const priorityValue = task.priority.toLowerCase() === "high" ? "high" : "low";
                      await knowledgeGraphManager.setEntityPriority(task.name, priorityValue);
                    } catch (error) {
                      console.error(`Error setting priority for new task ${task.name}: ${error}`);
                    }
                  }
                  
                  // Create sequencing relationships if specified
                  try {
                    // This task precedes another task
                    if (task.precedes) {
                      await knowledgeGraphManager.createRelations([{
                        from: task.name,
                        to: task.precedes,
                        relationType: "precedes"
                      }]);
                    }
                    
                    // This task follows another task
                    if (task.follows) {
                      await knowledgeGraphManager.createRelations([{
                        from: task.follows,
                        to: task.name,
                        relationType: "precedes"
                      }]);
                    }
                  } catch (error) {
                    console.error(`Error setting sequencing for task ${task.name}: ${error}`);
                  }
                }
                
                // Link tasks to project
                const taskRelations = taskEntities.map((task: {name: string}) => ({
                  from: projectUpdate.name,
                  to: task.name,
                  relationType: "contains"
                }));
                
                await knowledgeGraphManager.createRelations(taskRelations);
              }
              
              // Record session completion in persistent storage
              sessionState.push({
                type: 'session_completed',
                timestamp: new Date().toISOString(),
                summary: summary,
                project: focus
              });
              
              sessionStates.set(params.sessionId, sessionState);
              await saveSessionStates(sessionStates);
              
              // Prepare the summary message
              const summaryMessage = `# Development Session Recorded

I've recorded your development session focusing on ${focus}.

## Achievements Documented
${achievements.map((a: string) => `- ${a}`).join('\n') || "No achievements recorded."}

## Task Updates
${taskUpdates.map((t: {name: string, status: string}) => `- ${t.name}: ${t.status}`).join('\n') || "No task updates."}

## Project Status
Project ${projectUpdate.name} has been updated to: ${projectUpdate.status}

${newTasks && newTasks.length > 0 ? `## New Tasks Added
${newTasks.map((t: {name: string, description: string, priority?: string}) => `- ${t.name}: ${t.description} (Priority: ${t.priority || "medium"})`).join('\n')}` : "No new tasks added."}

## Session Summary
${summary}

Would you like me to perform any additional updates to the development knowledge graph?`;
              
              // Return the final result with the session recorded message
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({
                    success: true,
                    stageCompleted: params.stage,
                    nextStageNeeded: false,
                    stageResult: stageResult,
                    sessionRecorded: true,
                    summaryMessage: summaryMessage
                  }, null, 2)
                }]
              };
            } catch (error) {
              return {
                content: [{
                  type: "text",
                  text: JSON.stringify({
                    success: false,
                    error: `Error recording development session: ${error instanceof Error ? error.message : String(error)}`
                  }, null, 2)
                }]
              };
            }
          } else {
            // This is not the final stage or more stages are needed
            // Return intermediate result
            return {
              content: [{
                type: "text",
                text: JSON.stringify({
                  success: true,
                  stageCompleted: params.stage,
                  nextStageNeeded: params.nextStageNeeded,
                  stageResult: stageResult,
                  endSessionArgs: params.stage === "assembly" ? stageResult.stageData : null
                }, null, 2)
              }]
            };
          }
        } catch (error) {
          return {
            content: [{
              type: "text",
              text: JSON.stringify({ 
                success: false,
                error: error instanceof Error ? error.message : String(error)
              }, null, 2)
            }]
          };
        }
      }
    );

    // Connect the server to the transport
    const transport = new StdioServerTransport();
    await server.connect(transport);
  } catch (error) {
    console.error("Error starting server:", error);
    process.exit(1);
  }
}

// Run the main function
main().catch(error => {
  console.error("Unhandled error:", error);
  process.exit(1);
});

// Export the KnowledgeGraphManager for testing
export { KnowledgeGraphManager };
```
Page 3/9FirstPrevNextLast