Skip to main content
Glama
ejentum

ejentum-mcp

Official

harness_reasoning

Provides a cognitive scaffold to catch reasoning shortcuts and premature conclusions before answering complex analytical questions.

Instructions

Call BEFORE answering any analytical, diagnostic, planning, or multi-step reasoning question. Trigger queries include: "should I X or Y", "why is X happening", "what's the best approach", "what are the tradeoffs", "help me think through", "diagnose", "root cause", "plan/design X", "what are the implications of", "compare these approaches", "how do I decide between". Also call for cross-domain analysis, strategy questions, architecture decisions, or anything requiring multiple factors to be weighed before responding. The tool returns a cognitive scaffold (failure pattern to avoid, procedure, suppression vectors, falsification test) that you absorb internally before answering. It catches common LLM failure modes (causal shortcuts, premature conclusions, generic templates, surface pattern matching) that produce confidently wrong answers on these task types. DO NOT call for: simple factual lookups, syntax questions, file reads, code execution, basic confirmations, or restating something the user just said. When in doubt on a non-trivial reasoning task: call it. The cost is ~1 second of latency; the benefit is reasoning quality the model cannot reliably reproduce on its own. Pass a specific 1-2 sentence framing of WHAT you are reasoning about. Absorb the scaffold internally; do NOT echo bracket labels (NEGATIVE GATE, PROCEDURE, etc.) or harness vocabulary in your user-facing reply.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes1-2 sentence framing of the task you need the harness for. Be specific about WHAT you are trying to do, not what tool you want. Good: 'diagnose why a microservice returns 503s under load'. Bad: 'help me think'.

Implementation Reference

  • src/index.ts:14-20 (registration)
    The 'harness_reasoning' tool is registered in the HARNESSES array with mode 'reasoning' and a detailed description. It's dynamically registered via a loop (lines 55-77) that calls server.tool() for each harness in this array.
    const HARNESSES: HarnessTool[] = [
      {
        name: "harness_reasoning",
        mode: "reasoning",
        description:
          "Call BEFORE answering any analytical, diagnostic, planning, or multi-step reasoning question. Trigger queries include: \"should I X or Y\", \"why is X happening\", \"what's the best approach\", \"what are the tradeoffs\", \"help me think through\", \"diagnose\", \"root cause\", \"plan/design X\", \"what are the implications of\", \"compare these approaches\", \"how do I decide between\". Also call for cross-domain analysis, strategy questions, architecture decisions, or anything requiring multiple factors to be weighed before responding. The tool returns a cognitive scaffold (failure pattern to avoid, procedure, suppression vectors, falsification test) that you absorb internally before answering. It catches common LLM failure modes (causal shortcuts, premature conclusions, generic templates, surface pattern matching) that produce confidently wrong answers on these task types. DO NOT call for: simple factual lookups, syntax questions, file reads, code execution, basic confirmations, or restating something the user just said. When in doubt on a non-trivial reasoning task: call it. The cost is ~1 second of latency; the benefit is reasoning quality the model cannot reliably reproduce on its own. Pass a specific 1-2 sentence framing of WHAT you are reasoning about. Absorb the scaffold internally; do NOT echo bracket labels (NEGATIVE GATE, PROCEDURE, etc.) or harness vocabulary in your user-facing reply.",
      },
  • The input schema for all harness tools (including harness_reasoning) — a single required 'query' string field with description. No specific output schema is defined; the tool returns text content.
    const querySchema = {
      query: z
        .string()
        .min(1, "query must be a non-empty string")
        .describe(
          "1-2 sentence framing of the task you need the harness for. Be specific about WHAT you are trying to do, not what tool you want. Good: 'diagnose why a microservice returns 503s under load'. Bad: 'help me think'.",
        ),
    };
  • The handler function for all harness tools. It extracts 'query' from args and delegates to callHarness() with the harness's mode ('reasoning'), then returns the result as text content. Error handling wraps failures with 'Ejentum harness error' prefix.
    for (const harness of HARNESSES) {
      server.tool(
        harness.name,
        harness.description,
        querySchema,
        async ({ query }: { query: string }) => {
          try {
            const injection = await callHarness(query, harness.mode);
            return {
              content: [{ type: "text" as const, text: injection }],
            };
          } catch (err) {
            const message = err instanceof Error ? err.message : String(err);
            return {
              content: [
                { type: "text" as const, text: `Ejentum harness error: ${message}` },
              ],
              isError: true,
            };
          }
        },
      );
    }
  • The callHarness() helper function. Sends a POST request to the Ejentum Logic API with {query, mode} where mode='reasoning' for harness_reasoning. Handles auth, errors (401/403/429), parses the JSON array response, and extracts the mode-specific field using bracket notation.
    export async function callHarness(
      query: string,
      mode: HarnessMode,
    ): Promise<string> {
      const apiKey = process.env.EJENTUM_API_KEY;
      if (!apiKey || apiKey.trim().length === 0) {
        throw new Error(
          "EJENTUM_API_KEY is not set. Set it in your MCP client config (env block) and restart the client.",
        );
      }
    
      const apiUrl = process.env.EJENTUM_API_URL || DEFAULT_API_URL;
    
      let response: Response;
      try {
        response = await fetch(apiUrl, {
          method: "POST",
          headers: {
            Authorization: `Bearer ${apiKey}`,
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ query, mode }),
        });
      } catch (err) {
        const detail = err instanceof Error ? err.message : String(err);
        throw new Error(`Network error calling Ejentum API at ${apiUrl}: ${detail}`);
      }
    
      if (!response.ok) {
        const body = await response.text().catch(() => "");
        if (response.status === 401) {
          throw new LogicAPIError(
            401,
            body,
            "Unauthorized (401): check your EJENTUM_API_KEY value. Get one at https://ejentum.com/dashboard.",
          );
        }
        if (response.status === 403) {
          throw new LogicAPIError(
            403,
            body,
            "Forbidden (403): your API key does not have access to this mode. Multi modes require the Haki tier.",
          );
        }
        if (response.status === 429) {
          throw new LogicAPIError(
            429,
            body,
            "Rate limit exceeded (429): you have hit your tier's request limit. See https://ejentum.com/pricing.",
          );
        }
        throw new LogicAPIError(
          response.status,
          body,
          `Ejentum API returned ${response.status}: ${body.slice(0, 200)}`,
        );
      }
    
      let parsed: unknown;
      try {
        parsed = await response.json();
      } catch {
        throw new Error("Ejentum API returned invalid JSON");
      }
    
      if (!Array.isArray(parsed) || parsed.length === 0) {
        throw new Error(
          `Ejentum API returned unexpected shape (expected non-empty array): ${JSON.stringify(parsed).slice(0, 200)}`,
        );
      }
    
      const item = parsed[0] as LogicAPIResponseItem;
    
      // Bracket access is required because the `anti-deception` field name contains a hyphen.
      // Dot access (item.anti-deception) would parse as `item.anti - deception` and silently break.
      const injection = item[mode];
    
      if (typeof injection !== "string" || injection.length === 0) {
        throw new Error(
          `Ejentum API response missing or empty "${mode}" field. Got: ${JSON.stringify(item).slice(0, 200)}`,
        );
      }
    
      return injection;
    }
  • The HarnessMode type definition — 'reasoning' is one of the four valid modes, directly tied to the harness_reasoning tool.
    export type HarnessMode = "reasoning" | "code" | "anti-deception" | "memory";
Behavior5/5

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

No annotations provided, but description fully discloses behavior: returns a cognitive scaffold with specific components (failure patterns, procedure, etc.), to be absorbed internally. Mentions latency cost and common failure modes avoided.

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?

Efficiently packed with information, front-loaded purpose, structured with clear sections. Slightly lengthy but justified given the behavioral detail.

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

Completeness5/5

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

Single parameter, no output schema, but description fully explains purpose, usage, parameter format, internal behavior, and benefit. No gaps for an agent to use correctly.

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

Parameters5/5

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

Adds significant meaning beyond schema: specifies the query should be a specific 1-2 sentence framing, not just any string. Provides examples of good vs bad queries.

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 clearly states the tool is for analytical, diagnostic, planning, and multi-step reasoning questions, with explicit trigger queries and examples. It distinguishes itself from siblings by focusing on reasoning tasks.

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

Usage Guidelines5/5

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

Provides explicit when-to-use (analytical questions, trigger queries) and when-not-to-use (simple factual lookups, syntax questions, file reads, etc.). Also advises calling when in doubt on non-trivial tasks.

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/ejentum/ejentum-mcp'

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