Skip to content

chore: phi integration and mcp client improvements#14

Open
assagman wants to merge 3 commits intomainfrom
chore/updates
Open

chore: phi integration and mcp client improvements#14
assagman wants to merge 3 commits intomainfrom
chore/updates

Conversation

@assagman
Copy link
Owner

@assagman assagman commented Feb 3, 2026

Summary

  • Add phi.ts module for phi-specific functionality
  • Add prepare-phi-extension.ts build script
  • Extend CLI with phi setup command support
  • Improve MCP client with enhanced argument handling
  • Add safe-regex2 type definitions
  • Add regex validation and catalog improvements
  • Bump @modelcontextprotocol/sdk to 1.25.3
  • Fix plugin sensitive data redaction in logs

Changes

  • 3 commits moved from main
  • Tests added for new functionality

Fixes CVE-2026-0621 (ReDoS) flagged by Trivy.

Signed-off-by: assagman <ahmetsercansagman@gmail.com>
Avoid writing tool args/config secrets to disk and cap log line size.

Signed-off-by: assagman <ahmetsercansagman@gmail.com>
- Add phi.ts module for phi-specific functionality
- Add prepare-phi-extension.ts build script
- Extend CLI with phi setup command support
- Improve MCP client with enhanced argument handling
- Add safe-regex2 type definitions
- Add regex validation and catalog improvements
- Update tests for new functionality

Signed-off-by: assagman <ahmetsercansagman@gmail.com>
Copilot AI review requested due to automatic review settings February 3, 2026 09:38
@gemini-code-assist
Copy link

Summary of Changes

Hello @assagman, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly expands the agentsbox ecosystem by introducing a dedicated integration for Phi, allowing agentsbox tools and commands to be utilized within the Phi environment. Alongside this new integration, the MCP client has received several enhancements to its argument handling and error recovery, making it more robust. Critical security and performance improvements have also been implemented, focusing on regex validation, sensitive data logging, and catalog search efficiency. The CLI and build processes have been updated to support these new features and ensure a smoother developer experience.

Highlights

  • Phi Integration: Introduced a new phi.ts module and prepare-phi-extension.ts build script to enable agentsbox functionality as a Phi extension, including tool registration and commands within the Phi environment.
  • MCP Client Improvements: Enhanced the Model Context Protocol (MCP) client with improved argument handling, including a new inheritProcessEnv option to control environment variable inheritance for local servers, and robust error handling to ensure client cleanup on connection or tool listing failures.
  • Security and Performance Enhancements: Integrated safe-regex2 for regex validation to prevent Regular Expression Denial of Service (ReDoS) attacks, added sensitive data redaction in logs, and implemented truncation for searchable text and search limits to improve catalog performance and security.
  • CLI and Build Process Updates: Extended the CLI with a phi setup command, refactored the agent setup logic for reusability, and updated the build script to include the new Phi integration.
  • Dependency Updates: Bumped @modelcontextprotocol/sdk to 1.25.3 and @hono/node-server to 1.19.9, and added safe-regex2 as a new dependency.
Changelog
  • agentsbox.schema.json
    • Added inheritProcessEnv boolean property with a default of true to the local server configuration schema, allowing control over environment variable inheritance.
  • bun.lock
    • Updated @modelcontextprotocol/sdk from ^1.25.1 to ^1.25.3.
    • Updated @hono/node-server from 1.19.7 to 1.19.9.
    • Added safe-regex2@5.0.0 and its dependency ret@0.5.0.
  • package.json
    • Updated @modelcontextprotocol/sdk from ^1.25.1 to ^1.25.3.
    • Added safe-regex2 as a new dependency.
  • scripts/build.ts
    • Included src/phi.ts in the bun build command.
    • Added a step to run scripts/prepare-phi-extension.ts after preparing the pi extension.
  • scripts/prepare-phi-extension.ts
    • New script added to prepare the dist/phi-extension/ directory for symlinking into Phi's extensions directory.
    • Creates a minimal package.json and an index.js shim for ESM semantics and portability.
  • src/catalog/catalog.ts
    • Implemented truncation logic for buildSearchableText to limit the size of searchable text (max 4000 characters) to mitigate potential regex DoS attacks.
  • src/cli.ts
    • Added agentsbox setup phi command to the CLI usage and commands list.
    • Refactored planSetupPi into a more generic planSetupAgent function to support both Pi and Phi extensions.
    • Updated default paths to include phi extensions dir and a unified skills dir (~/.agents/skills).
    • Modified the main function to use planSetupAgent for both pi and phi targets, passing agent-specific directories and names.
  • src/config/schema.ts
    • Added inheritProcessEnv boolean property with a default of true to LocalServerConfigSchema.
  • src/mcp-client/local.ts
    • Introduced MINIMAL_ENV_KEYS and getMinimalProcessEnv function to provide a stripped-down environment.
    • Modified LocalMCPClient to respect the inheritProcessEnv configuration, allowing the child process to inherit either the full parent environment or a minimal one.
  • src/mcp-client/manager.ts
    • Improved the withTimeout utility to clear the timeout when the promise resolves or rejects, preventing potential resource leaks.
    • Added try...catch blocks around client.connect() and client.listTools() calls to ensure client.close() is called on failure, preventing orphaned processes.
  • src/mcp-client/types.ts
    • Added inheritProcessEnv?: boolean to LocalMCPServerConfig type definition.
  • src/phi.ts
    • New module defining the agentsbox integration for Phi.
    • Includes truncateHead and toToolResult functions for consistent output formatting and truncation.
    • Registers agentsbox_search_bm25, agentsbox_search_regex, agentsbox_execute, agentsbox_status, agentsbox_perf, and agentsbox_test as Phi tools.
    • Registers /agentsbox-status, /agentsbox-search, and /agentsbox-help as Phi commands.
  • src/plugin.ts
    • Refined parseToolName logic to ensure serverName does not contain underscores, making parsing unambiguous.
    • Added SENSITIVE_LOG_KEYS and redactForLog function to redact sensitive information from logs.
    • Modified the log function to use redactForLog and limit the size of extra log data.
    • Implemented validation to reject MCP server names containing underscores.
    • Clamped searchLimit values for BM25 and regex searches to a maximum of 50 results.
    • Changed logging of arguments in case of JSON parsing failure to argumentsLength instead of the full arguments string for security.
  • src/runtime.ts
    • Refined parseToolId logic to ensure serverName does not contain underscores.
    • Clamped searchLimit values for BM25 and regex searches to a maximum of 50 results.
  • src/search/regex.ts
    • Imported safeRegex from safe-regex2.
    • Added a check using safeRegex to reject patterns likely to cause catastrophic backtracking (ReDoS) before compiling the regex.
  • src/types/safe-regex2.d.ts
    • Added type definitions for the safe-regex2 module.
  • test/unit/cli-setup-phi.test.ts
    • New test file for agentsbox cli setup phi command, verifying dry-run output and behavior when dist/phi.js is missing.
  • test/unit/cli-setup-pi.test.ts
    • Updated assertions to reflect the new shared skills directory (~/.agents/skills/agentsbox) instead of ~/.pi/agent/skills/agentsbox.
  • test/unit/local-client.test.ts
    • Added a test case to verify that inheritProcessEnv=false correctly results in a minimal environment being passed to the child process.
  • test/unit/mcp-client.test.ts
    • Added tests to ensure that the client's close() method is called when connect() or listTools() operations fail, preventing resource leaks.
  • test/unit/regex.test.ts
    • Added a test case to confirm that the regex search function correctly rejects unsafe patterns identified as potential ReDoS vectors.
Activity
  • Three commits were moved from the main branch into this pull request.
  • New tests have been added to cover the newly introduced functionality and improvements.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Feb 3, 2026

Codecov Report

❌ Patch coverage is 71.52778% with 41 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/plugin.ts 50.00% 31 Missing ⚠️
src/runtime.ts 9.09% 10 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces integration for the phi agent, mirroring the existing pi integration, and brings several significant improvements across the codebase. The changes include adding a phi setup command to the CLI, creating a new phi.ts entrypoint, and refactoring the setup logic to be more generic.

I'm impressed with the numerous enhancements to security and robustness. The addition of safe-regex2 to prevent ReDoS, redaction of sensitive data in logs, and more robust error handling in the MCP client (ensuring connections are closed on failure) are all excellent improvements. The new inheritProcessEnv option also provides better control and security for local server processes.

The code is generally well-structured, and the addition of new tests for the new functionality is great. I've left a couple of comments regarding code duplication between the older OpenCode plugin implementation (src/plugin.ts) and the newer shared src/runtime.ts. Addressing this would further improve the maintainability of the project. Overall, this is a high-quality contribution.

Comment on lines +566 to +567
const rawLimit = args.limit ?? config.settings?.defaultLimit ?? 5;
const searchLimit = Math.max(1, Math.min(rawLimit, 50));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This search logic, including parameter validation like clamping the limit, is duplicated in src/runtime.ts (inside createAgentsboxRuntime). The AgentsboxPlugin appears to be re-implementing logic that is already encapsulated in the AgentsboxRuntime, which is used by other integrations like phi.

To improve maintainability and ensure consistent behavior across all integrations, consider refactoring AgentsboxPlugin to create and use an instance of AgentsboxRuntime. This would centralize the core logic for searching, execution, and status reporting.

Comment on lines 152 to +160
const underscoreIndex = fullName.indexOf("_");
if (underscoreIndex === -1) return null;
if (underscoreIndex <= 0 || underscoreIndex === fullName.length - 1) return null;

return {
serverName: fullName.substring(0, underscoreIndex),
toolName: fullName.substring(underscoreIndex + 1),
};
const serverName = fullName.substring(0, underscoreIndex);
const toolName = fullName.substring(underscoreIndex + 1);

if (!serverName || !toolName) return null;

return { serverName, toolName };

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This function can be simplified. The check if (!serverName || !toolName) return null; is redundant because the preceding condition if (underscoreIndex <= 0 || underscoreIndex === fullName.length - 1) already covers cases where serverName or toolName would be empty.

Additionally, this function is duplicated as parseToolName in src/plugin.ts. To improve maintainability, the logic should be centralized here, and src/plugin.ts should import and use this function.

Suggested change
const underscoreIndex = fullName.indexOf("_");
if (underscoreIndex === -1) return null;
if (underscoreIndex <= 0 || underscoreIndex === fullName.length - 1) return null;
return {
serverName: fullName.substring(0, underscoreIndex),
toolName: fullName.substring(underscoreIndex + 1),
};
const serverName = fullName.substring(0, underscoreIndex);
const toolName = fullName.substring(underscoreIndex + 1);
if (!serverName || !toolName) return null;
return { serverName, toolName };
const underscoreIndex = fullName.indexOf("_");
if (underscoreIndex <= 0 || underscoreIndex === fullName.length - 1) {
return null;
}
return {
serverName: fullName.substring(0, underscoreIndex),
toolName: fullName.substring(underscoreIndex + 1),
};

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class phi integration and hardens MCP/regex/logging behavior, including new setup workflows and safety checks.

Changes:

  • Introduces src/phi.ts plus build prep (prepare-phi-extension.ts) and CLI support for agentsbox setup phi.
  • Improves safety: regex ReDoS rejection, searchable text bounding, toolId parsing validation, and sensitive-log redaction.
  • Improves MCP robustness: clears timeout handles and closes clients on connect/listTools failures; adds inheritProcessEnv option for local servers.

Reviewed changes

Copilot reviewed 19 out of 21 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
test/unit/regex.test.ts Adds coverage for rejecting unsafe regex patterns (ReDoS).
test/unit/mcp-client.test.ts Adds tests ensuring clients are closed on initialization failures.
test/unit/local-client.test.ts Adds test for inheritProcessEnv=false minimal environment propagation.
test/unit/cli-setup-pi.test.ts Updates expected skill symlink destination to shared skills dir.
test/unit/cli-setup-phi.test.ts New tests for setup phi dry-run planning behavior.
src/types/safe-regex2.d.ts Adds local TS typings for safe-regex2.
src/search/regex.ts Adds ReDoS-oriented regex safety gate via safe-regex2.
src/runtime.ts Tightens toolId parsing and clamps search limits to a safe range.
src/plugin.ts Adds underscore validation for server names; improves redaction and avoids logging tool arguments verbatim.
src/phi.ts New phi extension entrypoint with runtime wiring and output truncation.
src/mcp-client/types.ts Adds inheritProcessEnv to local server config type.
src/mcp-client/manager.ts Clears timeout timers and ensures clients are closed on connect/listTools failure.
src/mcp-client/local.ts Implements optional minimal env inheritance for local MCP servers.
src/config/schema.ts Adds inheritProcessEnv to zod schema with default true.
src/cli.ts Adds setup phi and refactors setup planning into shared agent setup; uses shared skills dir.
src/catalog/catalog.ts Caps searchable text to mitigate worst-case regex/runtime behavior.
scripts/prepare-phi-extension.ts New script to generate portable dist/phi-extension/ shim without symlinks.
scripts/build.ts Builds src/phi.ts and runs phi extension preparation.
package.json Bumps MCP SDK and adds safe-regex2 dependency.
bun.lock Lockfile updates for new/updated dependencies.
agentsbox.schema.json Documents inheritProcessEnv in generated JSON schema.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +42 to +50
// Reject patterns likely to cause catastrophic backtracking (ReDoS)
if (!safeRegex(searchPattern)) {
return {
error: {
code: "invalid_pattern",
message: "Unsafe regex pattern (potential ReDoS)",
},
};
}
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

safe-regex2 can throw on invalid/unsupported patterns depending on its parser; since this call is outside a try/catch, an invalid pattern could crash the search path before the existing RegExp compilation try/catch runs. Wrap the safeRegex call in try/catch and return the same invalid_pattern error shape on exceptions (or fall back to the existing regex compilation error handling).

Copilot uses AI. Check for mistakes.
Comment on lines +219 to +236
const SENSITIVE_LOG_KEYS = new Set([
"authorization",
"cookie",
"set-cookie",
"token",
"accessToken",
"refreshToken",
"apiKey",
"apikey",
"secret",
"password",
"headers",
"arguments",
"environment",
"command",
"commandString",
"url",
]);
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redaction is currently case-sensitive, which can miss common variants like "Authorization", "Cookie", or "Set-Cookie". Consider normalizing keys during comparison (e.g., compare on k.toLowerCase()) and storing sensitive keys in lowercase only, while preserving the original key casing in the output object.

Copilot uses AI. Check for mistakes.
Comment on lines +252 to +260
const out: Record<string, unknown> = {};
for (const [k, v] of Object.entries(value)) {
if (SENSITIVE_LOG_KEYS.has(k)) {
out[k] = "[REDACTED]";
continue;
}
out[k] = redactForLog(v, depth + 1);
}
return out;
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redaction is currently case-sensitive, which can miss common variants like "Authorization", "Cookie", or "Set-Cookie". Consider normalizing keys during comparison (e.g., compare on k.toLowerCase()) and storing sensitive keys in lowercase only, while preserving the original key casing in the output object.

Copilot uses AI. Check for mistakes.
Comment on lines +272 to +276
const extraJson = extra ? JSON.stringify(redactForLog(extra)) : "";
const maxExtraBytes = 2048;
const extraStr = extraJson
? ` ${extraJson.length > maxExtraBytes ? `${extraJson.slice(0, maxExtraBytes)}…` : extraJson}`
: "";
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The log helper comment says "Never blocks or throws", but JSON.stringify can throw (e.g., circular structures or BigInt values). Wrap the stringify step in a try/catch and fall back to a safe placeholder (e.g., "[unserializable extra]") to preserve the "never throws" guarantee.

Copilot uses AI. Check for mistakes.
Comment on lines +89 to +94
const text = parts.join(" ");

// Bound match input size to mitigate worst-case regex/runtime behavior.
// (Regex DoS can happen even with short patterns if the input is huge.)
const MAX_SEARCHABLE_TEXT = 4000;
return text.length > MAX_SEARCHABLE_TEXT ? text.slice(0, MAX_SEARCHABLE_TEXT) : text;
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAX_SEARCHABLE_TEXT is reallocated on every call. Since it's a constant policy value, consider moving it to module scope (or a shared constants module) to avoid repeated allocation and to make the limit easier to reuse/tune.

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +35
function truncateHead(
text: string,
options: { maxBytes?: number; maxLines?: number } = {},
): TruncationResult {
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name truncateHead suggests removing content from the end, but the implementation/comment indicate it removes from the head and keeps the tail. Consider renaming to something like truncateToTail/keepTail (or adjusting naming/comment) to reduce ambiguity for callers and maintainers.

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +52
// Truncate from head (keep tail)
let keptLines = lines;
if (originalLines > maxLines) {
keptLines = lines.slice(-maxLines);
}
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name truncateHead suggests removing content from the end, but the implementation/comment indicate it removes from the head and keeps the tail. Consider renaming to something like truncateToTail/keepTail (or adjusting naming/comment) to reduce ambiguity for callers and maintainers.

Copilot uses AI. Check for mistakes.
// Symlink skill into pi's skill discovery path (~/.pi/agent/skills/agentsbox).
// Pi discovers skills from ~/.pi/agent/skills/**/SKILL.md recursively.
// Symlink skill into shared skills dir (~/.agents/skills/agentsbox).
// As of Feb 2026, all coding agents use this unified location.
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Time-anchored comments like "As of Feb 2026" can become stale quickly and are harder to evaluate later. Consider rephrasing to a timeless rationale (e.g., "All supported agents use this unified location") or linking to the source of truth (docs/spec) if available.

Suggested change
// As of Feb 2026, all coding agents use this unified location.
// All supported coding agents use this unified location for shared skills.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments