{"_id":"@arvoretech/await-until-mcp","_rev":"6-5e699b1e31397660878874758d140adf","name":"@arvoretech/await-until-mcp","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@arvoretech/await-until-mcp","version":"1.0.0","keywords":["mcp","await","polling","wait","condition","llm","ai","arvore"],"author":{"name":"Arvore"},"license":"MIT","_id":"@arvoretech/await-until-mcp@1.0.0","maintainers":[{"name":"joao.barros.arvore","email":"joao.barros@arvore.com.br"}],"homepage":"https://github.com/arvoreeducacao/arvore-mcp-servers#readme","bugs":{"url":"https://github.com/arvoreeducacao/arvore-mcp-servers/issues"},"bin":{"await-until-mcp":"dist/cli.js"},"dist":{"shasum":"7fa220dfdbaf2715cc8d58eb280d013dd55c591b","tarball":"https://registry.npmjs.org/@arvoretech/await-until-mcp/-/await-until-mcp-1.0.0.tgz","fileCount":22,"integrity":"sha512-npyAKOAxHtVjUqRPmIr6DwUIyV98lXuBrn3UQ9QxlAlZbtGTu7WCuDiTAIsLr9imePuYJ3dW8N7PW0nyg03+Hw==","signatures":[{"sig":"MEQCIG7ly+0MUGVFE1ESwJL0SVY6mbYrieyqsNvHDLAX3XJOAiBMwSaQGokF2+p1mEWieR1e3qjxAB/YT6jbaFj3GfNvRw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":79394},"main":"dist/index.js","type":"module","gitHead":"fe844befa75fee257b8b7dbbf86f52280e3c300f","scripts":{"dev":"tsx src/index.ts","lint":"eslint src/**/*.ts","test":"vitest run --passWithNoTests","build":"tsc","start":"node dist/index.js","lint:fix":"eslint src/**/*.ts --fix","test:cov":"vitest run --coverage --passWithNoTests"},"_npmUser":{"name":"joao.barros.arvore","email":"joao.barros@arvore.com.br"},"repository":{"url":"git+https://github.com/arvoreeducacao/arvore-mcp-servers.git","type":"git","directory":"packages/await-until"},"_npmVersion":"10.8.2","description":"MCP Server that polls conditions (shell commands, HTTP endpoints, files) until they match, with configurable intervals and timeouts","directories":{},"_nodeVersion":"20.20.0","dependencies":{"zod":"^3.22.4","@modelcontextprotocol/sdk":"~1.22.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/await-until-mcp_1.0.0_1773155353784_0.5938289541488695","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-03-10T15:09:13.690Z","modified":"2026-06-16T21:13:09.582Z","1.0.0":"2026-03-10T15:09:13.940Z"},"bugs":{"url":"https://github.com/arvoreeducacao/arvore-mcp-servers/issues"},"author":{"name":"Arvore"},"license":"MIT","homepage":"https://github.com/arvoreeducacao/arvore-mcp-servers#readme","keywords":["mcp","await","polling","wait","condition","llm","ai","arvore"],"repository":{"url":"git+https://github.com/arvoreeducacao/arvore-mcp-servers.git","type":"git","directory":"packages/await-until"},"description":"MCP Server that polls conditions (shell commands, HTTP endpoints, files) until they match, with configurable intervals and timeouts","maintainers":[{"email":"joao.barros@arvore.com.br","name":"joao.barros.arvore"},{"email":"rafasouza@protonmail.com","name":"rafsouza"},{"email":"pedro.adas@gmail.com","name":"pedro.adas"},{"email":"guilhermebscontact@gmail.com","name":"guilhermebs"},{"email":"ricardorbxx1@gmail.com","name":"ricardoraposorfox"},{"email":"jvgcunha2002@gmail.com","name":"jott4"},{"email":"vitor.piovezan@arvore.com.br","name":"vitor.piovezan"}],"readme":"# Await Until MCP Server\n\nA Model Context Protocol (MCP) server that provides polling/waiting primitives. Repeatedly checks conditions (shell commands, HTTP endpoints, files, or other MCP tools) at configurable intervals until they're met or time out.\n\n## Features\n\n- **Command Polling**: Execute shell commands until output matches a condition\n- **URL Polling**: Poll HTTP endpoints until they return expected status/body\n- **File Polling**: Watch filesystem until files exist, disappear, or contain content\n- **MCP Polling**: Call any other MCP server's tool and poll until the result matches — auto-discovers servers from your mcp.json (Kiro, Cursor, Claude Desktop)\n- **Configurable**: Interval, timeout, and match conditions for every tool\n- **MCP Protocol**: Communication via stdio transport\n- **TypeScript**: Fully typed with Zod validation\n- **No Configuration**: No environment variables required\n\n## Architecture\n\n```\nAgent calls await_until_* tool\n  → Await-Until MCP Server starts polling loop\n    → Each iteration: execute check (command/url/file/mcp)\n    → Evaluate match condition against output\n    → If matched → return success\n    → If not → sleep interval → retry\n    → If timeout → return failure\n```\n\nFor `await_until_mcp`, the server reads your IDE's `mcp.json` config, spawns the target MCP server as a child process via stdio, calls the specified tool, and evaluates the result.\n\n## Usage\n\n```bash\n# Development\npnpm dev\n\n# Production\npnpm build\nnode dist/index.js\n```\n\n## Available MCP Tools\n\n### `await_until_command`\n\nRepeatedly executes a shell command at a given interval until the output matches a condition or times out.\n\n**Parameters:**\n\n- `command` (string): Shell command to execute on each poll\n- `match` (string, optional): How to evaluate output (default: `exists`)\n  - `exists`: Exit code is 0\n  - `contains`: stdout contains the pattern\n  - `not_contains`: stdout does NOT contain the pattern\n  - `equals`: stdout exactly equals the pattern (trimmed)\n  - `not_equals`: stdout does NOT equal the pattern\n  - `regex`: stdout matches the regex pattern\n  - `not_empty`: stdout is not empty\n- `pattern` (string, optional): String or regex to match. Required for `contains`, `not_contains`, `equals`, `not_equals`, `regex`\n- `interval_seconds` (number, optional): Seconds between polls (default: 5, min: 1, max: 300)\n- `timeout_seconds` (number, optional): Max seconds to wait (default: 120, min: 1, max: 3600)\n- `cwd` (string, optional): Working directory for the command\n- `shell` (string, optional): Shell to use (default: `/bin/bash`)\n\n**Example — wait for a service to be healthy:**\n\n```json\n{\n  \"command\": \"curl -sf http://localhost:3000/health\",\n  \"match\": \"contains\",\n  \"pattern\": \"\\\"status\\\":\\\"ok\\\"\",\n  \"interval_seconds\": 5,\n  \"timeout_seconds\": 60\n}\n```\n\n**Example — wait for a Docker container to be running:**\n\n```json\n{\n  \"command\": \"docker inspect -f '{{.State.Running}}' my-container\",\n  \"match\": \"equals\",\n  \"pattern\": \"true\",\n  \"interval_seconds\": 3,\n  \"timeout_seconds\": 30\n}\n```\n\n### `await_until_url`\n\nPolls an HTTP endpoint at a given interval until it returns the expected status code and/or body content.\n\n**Parameters:**\n\n- `url` (string): URL to poll\n- `method` (string, optional): HTTP method — `GET`, `POST`, or `HEAD` (default: `GET`)\n- `expected_status` (number, optional): Expected HTTP status code. If omitted, any 2xx is accepted\n- `body_contains` (string, optional): String that the response body must contain\n- `headers` (object, optional): Custom headers to send\n- `interval_seconds` (number, optional): Seconds between polls (default: 5)\n- `timeout_seconds` (number, optional): Max seconds to wait (default: 120)\n\n**Example — wait for an API to be ready:**\n\n```json\n{\n  \"url\": \"http://localhost:4000/api/health\",\n  \"expected_status\": 200,\n  \"interval_seconds\": 5,\n  \"timeout_seconds\": 90\n}\n```\n\n### `await_until_file`\n\nPolls the filesystem at a given interval until a file exists, disappears, or contains expected content.\n\n**Parameters:**\n\n- `path` (string): Absolute or relative file path to watch\n- `match` (string, optional): Condition to check (default: `exists`)\n  - `exists`, `not_exists`, `contains`, `regex`, `not_empty`\n- `pattern` (string, optional): String or regex to match. Required for `contains`, `regex`\n- `interval_seconds` (number, optional): Seconds between polls (default: 3)\n- `timeout_seconds` (number, optional): Max seconds to wait (default: 120)\n\n**Example — wait for a build artifact:**\n\n```json\n{\n  \"path\": \"./dist/index.js\",\n  \"match\": \"exists\",\n  \"interval_seconds\": 3,\n  \"timeout_seconds\": 120\n}\n```\n\n**Example — wait for a lock file to be removed:**\n\n```json\n{\n  \"path\": \"/tmp/migration.lock\",\n  \"match\": \"not_exists\",\n  \"interval_seconds\": 5,\n  \"timeout_seconds\": 300\n}\n```\n\n### `await_until_mcp`\n\nPolls another MCP server's tool at a given interval until the result matches a condition or times out. Reads your IDE's `mcp.json` config to discover and spawn the target MCP server, then calls the specified tool repeatedly.\n\n**How it works:**\n\n1. Reads `mcp.json` from your workspace or global config (auto-detects Kiro, Cursor, Claude Desktop)\n2. Finds the server config by `server_name`\n3. Spawns the MCP server as a child process via stdio\n4. Calls `tool_name` with `tool_arguments` on each poll\n5. Evaluates the text result against the `match` condition\n6. Returns when matched or timed out\n\n**Parameters:**\n\n- `server_name` (string): Name of the MCP server as defined in your `mcp.json` (e.g. `datadog`, `slack`, `arvore-mysql`)\n- `tool_name` (string): Name of the MCP tool to call on each poll (e.g. `search_logs`, `query`)\n- `tool_arguments` (object, optional): Arguments to pass to the MCP tool on each call\n- `match` (string, optional): How to evaluate the result (default: `not_empty`)\n  - `contains`, `not_contains`, `equals`, `not_equals`, `regex`, `not_empty`\n- `pattern` (string, optional): String or regex to match. Required for `contains`, `not_contains`, `equals`, `not_equals`, `regex`\n- `interval_seconds` (number, optional): Seconds between polls (default: 10)\n- `timeout_seconds` (number, optional): Max seconds to wait (default: 120)\n- `mcp_config_path` (string, optional): Explicit path to `mcp.json`. Auto-detected if omitted\n\n**Config auto-detection order:**\n\n1. `mcp_config_path` (if provided)\n2. `.kiro/settings/mcp.json` (workspace)\n3. `.cursor/mcp.json` (workspace)\n4. `.vscode/mcp.json` (workspace)\n5. `~/.kiro/settings/mcp.json` (global)\n6. `~/.cursor/mcp.json` (global)\n7. `~/Library/Application Support/Claude/claude_desktop_config.json` (global)\n\n**Example — wait for a database row to appear:**\n\n```json\n{\n  \"server_name\": \"arvore-mysql\",\n  \"tool_name\": \"query\",\n  \"tool_arguments\": {\n    \"sql\": \"SELECT status FROM migrations WHERE name = 'add_users_table'\"\n  },\n  \"match\": \"contains\",\n  \"pattern\": \"completed\",\n  \"interval_seconds\": 5,\n  \"timeout_seconds\": 300\n}\n```\n\n**Example — wait for a LaunchDarkly flag to be enabled:**\n\n```json\n{\n  \"server_name\": \"launchdarkly\",\n  \"tool_name\": \"get_flag\",\n  \"tool_arguments\": {\n    \"key\": \"new-checkout-flow\",\n    \"environment\": \"production\"\n  },\n  \"match\": \"contains\",\n  \"pattern\": \"\\\"on\\\":true\",\n  \"interval_seconds\": 10,\n  \"timeout_seconds\": 120\n}\n```\n\n**Example — wait for a Datadog monitor to recover:**\n\n```json\n{\n  \"server_name\": \"datadog\",\n  \"tool_name\": \"list_monitors\",\n  \"tool_arguments\": {\n    \"name\": \"API Latency\",\n    \"groupStates\": [\"Alert\"]\n  },\n  \"match\": \"contains\",\n  \"pattern\": \"\\\"overall_state\\\":\\\"OK\\\"\",\n  \"interval_seconds\": 30,\n  \"timeout_seconds\": 600\n}\n```\n\n## MCP Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"await-until\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@arvoretech/await-until-mcp\"]\n    }\n  }\n}\n```\n\n## Development\n\n```bash\npnpm install\npnpm dev\npnpm build\npnpm lint\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}