#
tokens: 3125/50000 6/6 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── src
│   └── index.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
# Dependencies
node_modules/

# Build output
build/

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# VS Code files
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace

# macOS files
.DS_Store
.AppleDouble
.LSOverride

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# MCP Wait Timer Server

An MCP (Model Context Protocol) server providing a simple `wait` tool.

Watch the demo video: [https://www.youtube.com/watch?v=TaF_j9wrWVw](https://www.youtube.com/watch?v=TaF_j9wrWVw)

## Overview

This server exposes a single tool, `wait`, designed to introduce deliberate pauses into workflows executed by MCP clients (e.g., Cline, Claude Desktop, Cursor).

## Problem Solved

MCP clients and the AI models driving them often operate sequentially. After executing a command or action (like a web request, file operation, or API call), the model might proceed to the next step immediately. However, some actions require additional time to fully complete their effects (e.g., background processes finishing, web pages fully rendering after JavaScript execution, file system propagation).

Since the model cannot always reliably detect when these asynchronous effects are complete, it might proceed prematurely, leading to errors or incorrect assumptions in subsequent steps.

## Solution: The `wait` Tool

This server provides a `wait` tool that allows the user or the AI prompt to explicitly instruct the client to pause for a specified duration before continuing. This ensures that time-dependent operations have sufficient time to complete.

**Tool:** `wait`
*   **Description:** Pauses execution for a specified number of seconds.
*   **Input Parameter:**
    *   `duration_seconds` (number, required): The duration to wait, in seconds. Must be a positive number.

## Use Cases

*   **Web Automation:** Ensure dynamic content loads or scripts finish executing after page navigation or element interaction.
    ```
    Example Prompt: "Navigate to example.com, fill the login form, click submit, then wait for 5 seconds and capture a screenshot."
    ```
*   **Command Line Operations:** Allow time for background tasks, file writes, or service startups initiated by a shell command.
    ```
    Example Prompt: "Run 'npm run build', wait for 15 seconds, then check if the 'dist/app.js' file exists."
    ```
*   **API Interaction:** Add delays between API calls to handle rate limiting or wait for asynchronous job completion.
*   **Workflow Debugging:** Insert pauses to observe the state of the system at specific points during a complex task.

## Installation & Setup

This server requires Node.js (version 16 or higher).

### Step 1: Configure Your MCP Client

Add the following JSON block within the `"mcpServers": {}` object in your client's configuration file. Choose the file corresponding to your client and operating system:

**Configuration Block:**

```json
    "wait-timer": {
      "command": "npx",
      "args": ["mcp-wait-timer"],
      "env": {},
      "disabled": false,
      "autoApprove": []
    }
```

**Client Configuration File Locations:**

*   **Claude Desktop:**
    *   macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
    *   Windows: `%APPDATA%\Claude\claude_desktop_config.json`
    *   Linux: `~/.config/Claude/claude_desktop_config.json` *(Path may vary slightly)*

*   **VS Code Extension (Cline / "Claude Code"):**
    *   macOS: `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`
    *   Windows: `%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings\cline_mcp_settings.json`
    *   Linux: `~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`

*   **Cursor:**
    *   Global: `~/.cursor/mcp.json`
    *   Project-Specific: Create a file at `.cursor/mcp.json` within your project folder.

*   **Windsurf:**
    *   `~/.codeium/windsurf/mcp_config.json`

*   **Other Clients:**
    *   Consult the specific client's documentation for the location of its MCP configuration file. The JSON structure shown in the "Configuration Block" above should generally work.

### Step 2: Restart Client

After adding the configuration block and saving the file, **fully restart** your MCP client application for the changes to take effect. The first time the client starts the server, `npx` will automatically download the `mcp-wait-timer` package if it's not already cached.

## Usage Example

Once installed and enabled, you can instruct your MCP client:

```
"Please wait for 10 seconds before proceeding."
```

The client's AI model should recognize the intent and call the `wait` tool with `duration_seconds: 10`.

## Developed By

This tool was developed as part of the initiatives at [199 Longevity](https://www.199.company), a group focused on extending the frontiers of human health and longevity.

Learn more about our work in biotechnology at [199.bio](https://www.199.bio).

Project contributor: Boris Djordjevic

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "mcp-wait-timer",
  "version": "0.1.8",
  "description": "MCP server with a simple wait tool",
  "type": "module",
  "main": "build/index.js",
  "bin": {
    "mcp-wait-timer": "./build/index.js"
  },
  "scripts": {
    "build": "tsc && chmod +x build/index.js",
    "start": "node build/index.js"
  },
  "keywords": [
    "mcp",
    "model-context-protocol"
  ],
  "author": "Cline",
  "license": "MIT",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^0.4.0",
    "zod": "^3.22.4"
  },
  "devDependencies": {
    "@types/node": "^20.11.24",
    "typescript": "^5.3.3"
  },
  "files": [
    "build",
    "README.md",
    "LICENSE",
    "CHANGELOG.md"
  ]
}

```

--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.6] - 2025-03-29

### Fixed
- Use `z.coerce.number()` for `duration_seconds` to handle string inputs from clients like Claude Desktop.

## [0.1.5] - 2025-03-29

### Added
- `CHANGELOG.md` file.

## [0.1.4] - 2025-03-29

### Fixed
- Removed comments from the example JSON configuration block in `README.md`.

## [0.1.3] - 2025-03-29

### Added
- MIT `LICENSE` file.
- License section in `README.md`.

### Changed
- Updated `license` field in `package.json` to "MIT".

## [0.1.2] - 2025-03-29

### Fixed
- Refactored server code (`src/index.ts`) to align with MCP SDK examples (`Server` class, `setRequestHandler`).
- Reverted build script in `package.json` to use `tsc` instead of `esbuild`.

## [0.1.1] - 2025-03-29

### Fixed
- Attempted fix for `npx` execution using `esbuild` bundling (later reverted).
- Updated `package.json` build script to use `esbuild`.

## [0.1.0] - 2025-03-29

### Added
- Initial release of the `mcp-wait-timer` server.
- Basic `wait` tool functionality.
- Configuration for `npx` execution via `package.json` `bin` field.

```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  CallToolResult,
  ErrorCode,
  ListToolsRequestSchema,
  McpError,
  Tool,
} from '@modelcontextprotocol/sdk/types.js';
import { z } from 'zod';

// --- Tool Logic ---

const waitInputSchemaShape = {
  duration_seconds: z.coerce.number().positive().describe('The number of seconds to wait'), // Use coerce.number()
};
const waitInputSchema = z.object(waitInputSchemaShape);

async function waitHandler(args: z.infer<typeof waitInputSchema>): Promise<CallToolResult> {
  const { duration_seconds } = args;
  try {
    console.error(`[mcp-wait-timer] Waiting for ${duration_seconds} seconds...`);
    await new Promise(resolve => setTimeout(resolve, duration_seconds * 1000));
    console.error(`[mcp-wait-timer] Wait finished.`);
    return {
      isError: false,
      content: [{ type: 'text', text: `Successfully waited for ${duration_seconds} seconds.` }],
    };
  } catch (error: any) {
    console.error(`[mcp-wait-timer] Error during wait: ${error.message}`);
    // Ensure error responses also conform to CallToolResult
    return {
      isError: true,
      content: [{ type: 'text', text: `Error waiting: ${error.message}` }],
    };
  }
}

// --- Tool Definition ---

const WAIT_TOOL: Tool = {
  name: 'wait',
  description: 'Waits for a specified duration in seconds.',
  inputSchema: {
    type: 'object',
    properties: waitInputSchemaShape,
    required: ['duration_seconds'],
  },
};

// --- Server Setup ---

const server = new Server({
  name: 'mcp-wait-timer',
  version: '0.1.1', // Will update later before publishing
  // Capabilities are defined implicitly via setRequestHandler
});

// --- Request Handlers ---

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [WAIT_TOOL],
}));

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === WAIT_TOOL.name) {
    const parseResult = waitInputSchema.safeParse(request.params.arguments);
    if (!parseResult.success) {
      throw new McpError(
        ErrorCode.InvalidParams,
        `Invalid arguments for tool ${WAIT_TOOL.name}: ${parseResult.error.message}`
      );
    }
    return waitHandler(parseResult.data);
  }
  throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
});

// --- Main Execution ---

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('[mcp-wait-timer] Server running on stdio');
  // Keep alive
  await new Promise(() => {});
}

main().catch((error) => {
  console.error('[mcp-wait-timer] Fatal error:', error);
  process.exit(1);
});

// Graceful shutdown
process.on('SIGINT', async () => {
  console.error('[mcp-wait-timer] SIGINT received, shutting down...');
  await server.close();
  process.exit(0);
});

process.on('SIGTERM', async () => {
  console.error('[mcp-wait-timer] SIGTERM received, shutting down...');
  await server.close();
  process.exit(0);
});

```