Skip to main content
Glama

Consult Opus Advisor

consult_opus
Read-only

Get strategic advice from Claude Opus for architecture decisions, complex debugging, and code review. Maintains a per-project consultation log for continuity.

Instructions

Consult Claude Opus 4.7 for strategic advice. Opus runs via the Claude Code CLI with your existing subscription — no API key needed. The advisor maintains a per-project consultation log for continuity across calls. History is capped by both entry count (5) and token budget (~6K tokens) to prevent context bloat. Use this for architecture decisions, complex debugging, code review, or any problem that benefits from deeper reasoning.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
questionYesThe question or problem you need advice on. Be specific about what decision you're facing or what you're stuck on.
contextNoAdditional context: relevant code snippets, error messages, constraints, or background. Include enough that the advisor can give specific guidance without needing to read files.
effortNoReasoning effort level for Opus. 'low' for quick opinions, 'medium' (default) for thorough advice, 'high' for deep analysis.medium
filesNoFile paths (relative to project root) to include as code context. Each file is read and prepended as a labeled code block. Max 50KB per file, 200KB total. Example: ['src/index.ts', 'lib/utils.ts']
include_historyNoWhether to include prior consultation history for continuity. Defaults to true. Set to false for standalone questions unrelated to prior advice.

Implementation Reference

  • src/index.ts:362-410 (registration)
    Registration of 'consult_opus' MCP tool with inputSchema, description, title, and annotations.
    server.registerTool("consult_opus", {
      title: "Consult Opus Advisor",
      description:
        "Consult Claude Opus 4.7 for strategic advice. Opus runs via the Claude Code CLI " +
        "with your existing subscription — no API key needed. The advisor maintains a " +
        "per-project consultation log for continuity across calls. History is capped by " +
        "both entry count (5) and token budget (~6K tokens) to prevent context bloat. " +
        "Use this for architecture decisions, complex debugging, code review, or any " +
        "problem that benefits from deeper reasoning.",
      inputSchema: {
        question: z
          .string()
          .describe(
            "The question or problem you need advice on. Be specific about what decision " +
            "you're facing or what you're stuck on.",
          ),
        context: z
          .string()
          .optional()
          .describe(
            "Additional context: relevant code snippets, error messages, constraints, or " +
            "background. Include enough that the advisor can give specific guidance without " +
            "needing to read files.",
          ),
        effort: z
          .enum(["low", "medium", "high"])
          .optional()
          .default("medium")
          .describe(
            "Reasoning effort level for Opus. 'low' for quick opinions, 'medium' (default) " +
            "for thorough advice, 'high' for deep analysis.",
          ),
        files: z
          .array(z.string())
          .optional()
          .describe(
            "File paths (relative to project root) to include as code context. " +
            "Each file is read and prepended as a labeled code block. " +
            "Max 50KB per file, 200KB total. Example: ['src/index.ts', 'lib/utils.ts']",
          ),
        include_history: z
          .boolean()
          .optional()
          .default(true)
          .describe(
            "Whether to include prior consultation history for continuity. Defaults to true. " +
            "Set to false for standalone questions unrelated to prior advice.",
          ),
      },
  • Input schema for consult_opus: question (string, required), context (string, optional), effort (enum: low/medium/high, optional, default medium), files (string array, optional), include_history (boolean, optional, default true).
    inputSchema: {
      question: z
        .string()
        .describe(
          "The question or problem you need advice on. Be specific about what decision " +
          "you're facing or what you're stuck on.",
        ),
      context: z
        .string()
        .optional()
        .describe(
          "Additional context: relevant code snippets, error messages, constraints, or " +
          "background. Include enough that the advisor can give specific guidance without " +
          "needing to read files.",
        ),
      effort: z
        .enum(["low", "medium", "high"])
        .optional()
        .default("medium")
        .describe(
          "Reasoning effort level for Opus. 'low' for quick opinions, 'medium' (default) " +
          "for thorough advice, 'high' for deep analysis.",
        ),
      files: z
        .array(z.string())
        .optional()
        .describe(
          "File paths (relative to project root) to include as code context. " +
          "Each file is read and prepended as a labeled code block. " +
          "Max 50KB per file, 200KB total. Example: ['src/index.ts', 'lib/utils.ts']",
        ),
      include_history: z
        .boolean()
        .optional()
        .default(true)
        .describe(
          "Whether to include prior consultation history for continuity. Defaults to true. " +
          "Set to false for standalone questions unrelated to prior advice.",
        ),
    },
  • Handler function for consult_opus. Builds prompt with optional history, files, and context, calls runClaude() with model='opus', logs the consultation, and returns advice text.
    }, async ({ question, context, effort, files, include_history }) => {
      const startTime = Date.now();
      try {
        await ensureAdvisorDir();
        const cwd = process.cwd();
    
        // Build the prompt with optional history, files, and context
        const parts: string[] = [];
        let historyTokens = 0;
        let fileTokens = 0;
    
        if (include_history) {
          const history = await readAdvisorLog();
          const recentHistory = getRecentHistory(history, 5, MAX_HISTORY_TOKENS);
          if (recentHistory) {
            historyTokens = estimateTokens(recentHistory);
            parts.push(
              `## Prior Consultation History (for continuity — ~${historyTokens} tokens)`,
              recentHistory,
              "",
            );
          }
        }
    
        // Read and inject file contents
        if (files && files.length > 0) {
          const fileResult = await readFilesForContext(files, cwd);
          if (fileResult.blocks) {
            fileTokens = estimateTokens(fileResult.blocks);
            parts.push(
              `## Files (${fileResult.fileCount} files, ~${fileTokens} tokens)`,
              fileResult.blocks,
              "",
            );
          }
          if (fileResult.errors.length > 0) {
            parts.push(
              `> File warnings: ${fileResult.errors.join("; ")}`,
              "",
            );
          }
        }
    
        parts.push("## Current Question", question);
        if (context) {
          parts.push("", "## Context", context);
        }
    
        const fullPrompt = parts.join("\n");
    
        const result = await runClaude(fullPrompt, {
          model: "opus",
          effort: effort ?? "medium",
          systemPrompt: ADVISOR_SYSTEM_PROMPT,
        });
    
        const latencyMs = Date.now() - startTime;
    
        // Log the consultation (include file names in context for the log)
        const logContext = [
          context || "",
          files && files.length > 0 ? `\nFiles consulted: ${files.join(", ")}` : "",
        ].filter(Boolean).join("") || undefined;
    
        await appendToLog(question, logContext, result.output);
    
        // Write structured metadata
        await appendMetadata({
          timestamp: new Date().toISOString(),
          effort: effort ?? "medium",
          latencyMs,
          questionTokens: estimateTokens(question),
          contextTokens: (context ? estimateTokens(context) : 0) + fileTokens,
          historyTokens,
          adviceTokens: estimateTokens(result.output),
          signal: result.signal,
        });
    
        return {
          content: [{ type: "text" as const, text: result.output }],
        };
      } catch (err) {
        const latencyMs = Date.now() - startTime;
        const message =
          err instanceof Error ? err.message : "Unknown error consulting Opus";
    
        // Log failed attempts to metadata too
        await appendMetadata({
          timestamp: new Date().toISOString(),
          effort: effort ?? "medium",
          latencyMs,
          questionTokens: estimateTokens(question),
          contextTokens: context ? estimateTokens(context) : 0,
          historyTokens: 0,
          adviceTokens: 0,
          signal: message.includes("signal") ? message : null,
        }).catch(() => {});
    
        return {
          content: [{ type: "text" as const, text: `Advisor error: ${message}` }],
          isError: true,
        };
      }
    });
  • getAdvisorDir() - determines project-specific log directory using SHA256 hash of cwd.
    function getAdvisorDir(): string {
      if (process.env.ADVISOR_LOG_DIR) {
        return process.env.ADVISOR_LOG_DIR;
      }
      const home = process.env.HOME || "~";
      const cwd = process.cwd();
      const projectName = basename(cwd);
      const projectHash = createHash("sha256").update(cwd).digest("hex").slice(0, 8);
      return join(home, ".opus-advisor", `${projectName}-${projectHash}`);
    }
  • runClaude() - spawns the claude CLI process with -p flag, pipes prompt via stdin, handles output/errors/signals.
    function runClaude(prompt: string, options: {
      model: string;
      effort: string;
      systemPrompt: string;
      maxTurns?: number;
      cwd?: string;
    }): Promise<ClaudeResult> {
      return new Promise((resolve, reject) => {
        const args = [
          "-p",
          "--model", options.model,
          "--effort", options.effort,
          "--system-prompt", options.systemPrompt,
          "--max-turns", String(options.maxTurns ?? 1),
          "--no-session-persistence",
          "--disable-slash-commands",
        ];
    
        const child = spawn("claude", args, {
          cwd: options.cwd || process.cwd(),
          stdio: ["pipe", "pipe", "pipe"],
          env: { ...process.env },
          timeout: 300_000, // 5 min
        });
    
        let stdout = "";
        let stderr = "";
    
        child.stdout.on("data", (data: Buffer) => {
          stdout += data.toString();
        });
    
        child.stderr.on("data", (data: Buffer) => {
          stderr += data.toString();
        });
    
        // Pipe the prompt via stdin, then close it
        child.stdin.write(prompt);
        child.stdin.end();
    
        child.on("error", (err) => {
          reject(new Error(`Failed to spawn claude CLI: ${err.message}`));
        });
    
        child.on("close", (code, signal) => {
          // If killed by signal (timeout, OOM, etc.), discard partial output
          if (signal) {
            reject(
              new Error(
                `claude CLI killed by signal ${signal}. Partial output discarded.\nstderr: ${stderr.slice(0, 500)}`,
              ),
            );
            return;
          }
          if (code !== 0) {
            reject(
              new Error(
                `claude CLI exited with code ${code}\nstderr: ${stderr.slice(0, 500)}`,
              ),
            );
            return;
          }
          const output = stdout.trim();
          if (!output) {
            reject(new Error("claude CLI returned empty output"));
            return;
          }
          resolve({ output, signal: null });
        });
      });
    }
Behavior5/5

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

The description reveals multiple behavioral traits beyond annotations: it maintains a per-project consultation log with entry (5) and token (~6K) caps, and explains the subscription model ('no API key needed'). Annotations already mark it as read-only and open-world, and the description adds valuable context without contradiction.

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

Conciseness5/5

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

The description is approximately 100 words and front-loaded with the main purpose. Every sentence adds value: subscription details, history management, limits, and explicit use cases. No redundancy or filler.

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

Completeness4/5

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

Given no output schema and moderate complexity, the description covers the essential aspects: purpose, mechanism, context management, and suitable use cases. It could be slightly improved by mentioning the response format or an example, but overall it is sufficient for an agent to understand the tool.

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

Parameters4/5

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

Schema has 100% coverage for 5 parameters. The description adds value by explaining the history cap (entry count and token budget) that directly informs the include_history parameter. It does not repeat schema descriptions, and the effort parameter's enum is not elaborated, but the overall context aids parameter usage.

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 explicitly states 'Consult Claude Opus 4.7 for strategic advice', providing a clear verb and resource. It distinguishes the tool from its siblings (log management) and lists specific use cases like architecture decisions and complex debugging.

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 gives clear guidance on when to use the tool ('Use this for architecture decisions, complex debugging, code review'), but does not explicitly mention when not to use it or compare it to alternatives. The siblings are for log management, so no direct competition, but exclusion criteria are missing.

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/Divinci-AI/opus-advisor-mcp'

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