Skip to main content
Glama

create_status_watch

Register a webhook watch to monitor AI service status transitions. When a provider's status becomes operational, degraded, or down, or changes, your callback URL receives a POST notification. Each watch costs 1 credit and lasts 90 days.

Instructions

Register a webhook watch on a service status transition (e.g. anthropic becomes down). Costs 1 credit. Watch lives 90 days.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
providerYesProvider name (e.g. anthropic, openai)
opYesbecomes = transitions to a specific value; changes = any transition
valueNoRequired when op is becomes
callback_urlYesHTTPS URL to POST to when the watch fires
secretNoOptional HMAC shared secret

Implementation Reference

  • The 'create_status_watch' tool is defined via server.tool(). It accepts provider, op, value, callback_url, and optional secret. It POSTs to /premium/watches with a spec of type 'status' and returns the created watch ID, expiry, and remaining credits.
    // ── Tool: create_status_watch (1 credit) ────────────────────────────
    
    server.tool(
      'create_status_watch',
      'Register a webhook watch on a service status transition (e.g. anthropic becomes down). Costs 1 credit. Watch lives 90 days.',
      {
        provider: z.string().describe('Provider name (e.g. anthropic, openai)'),
        op: z.enum(['becomes', 'changes']).describe('becomes = transitions to a specific value; changes = any transition'),
        value: z.enum(['operational', 'degraded', 'down']).optional().describe('Required when op is becomes'),
        callback_url: z.string().describe('HTTPS URL to POST to when the watch fires'),
        secret: z.string().optional().describe('Optional HMAC shared secret'),
      },
      async ({ provider, op, value, callback_url, secret }) => {
        const body: Record<string, unknown> = {
          spec: { type: 'status', provider, op, ...(value ? { value } : {}) },
          callback_url,
        };
        if (secret !== undefined) body.secret = secret;
        const data = (await fetchJSON('/premium/watches', { method: 'POST', body, auth: true })) as {
          watch: { id: string; expires_at: string };
          billing?: { credits_remaining?: number };
        };
        return {
          content: [
            {
              type: 'text' as const,
              text: `Created watch ${data.watch.id} (expires ${data.watch.expires_at}). Credits remaining: ${data.billing?.credits_remaining ?? '?'}`,
            },
          ],
        };
      },
    );
  • The tool is registered with the McpServer instance on line 844 using server.tool() with the name 'create_status_watch'.
    server.tool(
      'create_status_watch',
      'Register a webhook watch on a service status transition (e.g. anthropic becomes down). Costs 1 credit. Watch lives 90 days.',
      {
        provider: z.string().describe('Provider name (e.g. anthropic, openai)'),
        op: z.enum(['becomes', 'changes']).describe('becomes = transitions to a specific value; changes = any transition'),
        value: z.enum(['operational', 'degraded', 'down']).optional().describe('Required when op is becomes'),
        callback_url: z.string().describe('HTTPS URL to POST to when the watch fires'),
        secret: z.string().optional().describe('Optional HMAC shared secret'),
      },
      async ({ provider, op, value, callback_url, secret }) => {
        const body: Record<string, unknown> = {
          spec: { type: 'status', provider, op, ...(value ? { value } : {}) },
          callback_url,
        };
        if (secret !== undefined) body.secret = secret;
        const data = (await fetchJSON('/premium/watches', { method: 'POST', body, auth: true })) as {
          watch: { id: string; expires_at: string };
          billing?: { credits_remaining?: number };
        };
        return {
          content: [
            {
              type: 'text' as const,
              text: `Created watch ${data.watch.id} (expires ${data.watch.expires_at}). Credits remaining: ${data.billing?.credits_remaining ?? '?'}`,
            },
          ],
        };
      },
    );
  • Input schema defined inline using Zod: provider (string), op (enum: becomes/changes), value (optional enum: operational/degraded/down), callback_url (string), secret (optional string).
    {
      provider: z.string().describe('Provider name (e.g. anthropic, openai)'),
      op: z.enum(['becomes', 'changes']).describe('becomes = transitions to a specific value; changes = any transition'),
      value: z.enum(['operational', 'degraded', 'down']).optional().describe('Required when op is becomes'),
      callback_url: z.string().describe('HTTPS URL to POST to when the watch fires'),
      secret: z.string().optional().describe('Optional HMAC shared secret'),
    },
  • The fetchJSON helper function handles all HTTP calls to the TensorFeed API, including auth via TENSORFEED_TOKEN, Content-Type headers, error handling for 402/401, and JSON parsing. It is used by create_status_watch to POST to /premium/watches.
    async function fetchJSON(path: string, opts: FetchOptions = {}): Promise<unknown> {
      const headers: Record<string, string> = {
        'User-Agent': `TensorFeed-MCP/${SDK_VERSION}`,
      };
      if (opts.body !== undefined) headers['Content-Type'] = 'application/json';
      if (opts.auth) {
        const token = process.env.TENSORFEED_TOKEN;
        if (!token) {
          throw new Error(
            'TENSORFEED_TOKEN env var is not set. Premium MCP tools require a bearer token. ' +
              'Buy credits at https://tensorfeed.ai/developers/agent-payments and pass the returned tf_live_... token via the TENSORFEED_TOKEN env var in your MCP client config.',
          );
        }
        headers['Authorization'] = `Bearer ${token}`;
      }
      const res = await fetch(`${API_BASE}${path}`, {
        method: opts.method ?? 'GET',
        headers,
        ...(opts.body !== undefined ? { body: JSON.stringify(opts.body) } : {}),
      });
      if (!res.ok) {
        let errPayload: unknown;
        try {
          errPayload = await res.json();
        } catch {
          errPayload = await res.text().catch(() => '');
        }
        if (res.status === 402) {
          throw new Error(
            `Payment required (402). Your token may be out of credits. Top up at https://tensorfeed.ai/developers/agent-payments. Detail: ${JSON.stringify(errPayload)}`,
          );
        }
        if (res.status === 401) {
          throw new Error(
            `Token rejected (401). Check that TENSORFEED_TOKEN is set to a valid tf_live_... token. Detail: ${JSON.stringify(errPayload)}`,
          );
        }
        throw new Error(`API error ${res.status}: ${JSON.stringify(errPayload)}`);
      }
      return res.json();
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must cover behavioral traits. It discloses cost (1 credit) and expiration (90 days), but omits details such as what the webhook expects on trigger, authentication requirements, or error handling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One efficient sentence stating purpose, cost, and lifetime. Front-loaded with key information, no redundant words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite 5 parameters and no output schema, the description covers core purpose, cost, and lifetime. However, it lacks guidance on the callback URL format, secret generation, or what happens when the watch fires, leaving gaps for an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema has 100% description coverage, so baseline is 3. The description does not add any new parameter-level meaning beyond the schema's own descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description specifies 'Register a webhook watch on a service status transition' with an example, clearly distinguishing from sibling watch tools like create_digest_watch and create_price_watch.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use (monitoring status transitions) and adds cost/lifetime context, but does not explicitly state when not to use or compare with alternative tools like create_price_watch.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/RipperMercs/tensorfeed'

If you have feedback or need assistance with the MCP directory API, please join our Discord server