MCP exposure & input validation TODO's Completion#349
MCP exposure & input validation TODO's Completion#349MarawanYakout wants to merge 40 commits intoGitlawb:mainfrom
Conversation
…t/openclaude into oauth-securestorage
|
solved merge conflicts |
* Remove internal-only tooling without changing external runtime contracts This trims the lowest-risk internal-only surfaces first: deleted internal modules are replaced by build-time no-op stubs, the bundled stuck skill is removed, and the insights S3 upload path now stays local-only. The privacy verifier is expanded and the remaining bundled internal Slack/Artifactory strings are neutralized without broad repo-wide renames. Constraint: Keep the first PR deletion-heavy and avoid mass rewrites of USER_TYPE, tengu, or claude_code identifiers Rejected: One-shot DMCA cleanup branch | too much semantic risk for a first PR Confidence: medium Scope-risk: moderate Reversibility: clean Directive: Treat full-repo typecheck as a baseline issue on this upstream snapshot; do not claim this commit introduced the existing non-Phase-A errors without isolating them first Tested: bun run build Tested: bun run smoke Tested: bun run verify:privacy Not-tested: Full repo typecheck (currently fails on widespread pre-existing upstream errors outside this change set) * Keep minimal source shims so CI can import Phase A cleanup paths The first PR removed internal-only source files entirely, but CI provider and context tests import those modules directly from source rather than through the build-time no-telemetry stubs. This restores tiny no-op source shims so tests and local source imports resolve while preserving the same external runtime behavior. Constraint: GitHub Actions runs source-level tests in addition to bundled build/privacy checks Rejected: Revert the entire deletion pass | unnecessary once the import contract is satisfied by small shims Confidence: high Scope-risk: narrow Reversibility: clean Directive: For later cleanup phases, treat build-time stubs and source-test imports as separate compatibility surfaces Tested: bun run build Tested: bun run smoke Tested: bun run verify:privacy Tested: bun run test:provider Tested: bun run test:provider-recommendation Not-tested: Full repo typecheck (still noisy on this upstream snapshot) --------- Co-authored-by: anandh8x <test@example.com>
This pass rewrites comment-only ANT-ONLY markers to neutral internal-only language across the source tree without changing runtime strings, flags, commands, or protocol identifiers. The goal is to lower obvious internal prose leakage while keeping the diff mechanically safe and easy to review. Constraint: Phase B is limited to comments/prose only; runtime strings and user-facing labels remain deferred Rejected: Broad search-and-replace across strings and command descriptions | too risky for a prose-only pass Confidence: high Scope-risk: narrow Reversibility: clean Directive: Remaining ANT-ONLY hits are mostly runtime/user-facing strings and should be handled separately from comment cleanup Tested: bun run build Tested: bun run smoke Tested: bun run verify:privacy Tested: bun run test:provider Tested: bun run test:provider-recommendation Not-tested: Full repo typecheck (upstream baseline remains noisy) Co-authored-by: anandh8x <test@example.com>
) This is a small prose-only follow-up that rewrites clearly internal or explanatory Anthropic comment language to neutral wording in a handful of high-confidence files. It avoids runtime strings, flags, command labels, protocol identifiers, and provider-facing references. Constraint: Keep this pass narrowly scoped to comments/documentation only Rejected: Broader Anthropic comment sweep across functional API/protocol references | too ambiguous for a safe prose-only PR Confidence: high Scope-risk: narrow Reversibility: clean Directive: Leave functional Anthropic references (API behavior, SDKs, URLs, provider labels, protocol docs) for separate reviewed passes Tested: bun run build Tested: bun run smoke Tested: bun run verify:privacy Tested: bun run test:provider Tested: bun run test:provider-recommendation Not-tested: Full repo typecheck (upstream baseline remains noisy) Co-authored-by: anandh8x <test@example.com>
This pass rewrites a small set of ant-only diagnostic and UI labels to neutral internal wording while leaving command definitions, flags, and runtime logic untouched. It focuses on internal debug output, dead UI branches, and noninteractive headings rather than broader product text. Constraint: Label cleanup only; do not change command semantics or ant-only logic gates Rejected: Renaming ant-only command descriptions in main.tsx | broader UX surface better handled in a separate reviewed pass Confidence: high Scope-risk: narrow Reversibility: clean Directive: Remaining ANT-ONLY hits are mostly command descriptions and intentionally deferred user-facing strings Tested: bun run build Tested: bun run smoke Tested: bun run verify:privacy Tested: bun run test:provider Tested: bun run test:provider-recommendation Not-tested: Full repo typecheck (upstream baseline remains noisy) Co-authored-by: anandh8x <test@example.com>
This extends the label-only cleanup to the remaining internal-only command, debug, and heading strings so the source tree no longer contains ANT-ONLY markers. The pass still avoids logic changes and only renames labels shown in internal or gated surfaces. Constraint: Update the existing label-cleanup PR without widening scope into behavior changes Rejected: Leave the last ANT-ONLY strings for a later pass | low-cost cleanup while the branch is already focused on labels Confidence: high Scope-risk: narrow Reversibility: clean Directive: The next phase should move off label cleanup and onto a separately scoped logic or rebrand slice Tested: bun run build Tested: bun run smoke Tested: bun run verify:privacy Tested: bun run test:provider Tested: bun run test:provider-recommendation Not-tested: Full repo typecheck (upstream baseline remains noisy) Co-authored-by: anandh8x <test@example.com>
This follow-up Phase C-lite slice replaces purely internal helper modules with stable external no-op surfaces and collapses internal elevated error logging to a no-op. The change removes additional USER_TYPE-gated helper behavior without touching product-facing runtime flows. Constraint: Keep this PR limited to isolated helper modules that are already external no-ops in practice Rejected: Pulling in broader speculation or logging sink changes | less isolated and easier to debate during review Confidence: high Scope-risk: narrow Reversibility: clean Directive: Continue Phase C with similarly isolated helpers before moving into mixed behavior files Tested: bun run build Tested: bun run smoke Tested: bun run verify:privacy Tested: bun run test:provider Tested: bun run test:provider-recommendation Not-tested: Full repo typecheck (upstream baseline remains noisy) Co-authored-by: anandh8x <test@example.com>
* Remove internal-only bundled skills and mock rate-limit behavior This takes the next planned Phase C-lite slice by deleting bundled skills that only ever registered for internal users and replacing the internal mock rate-limit helper with a stable no-op external stub. The external build keeps the same behavior while removing a concentrated block of USER_TYPE-gated dead code. Constraint: Limit this PR to isolated internal-only helpers and avoid bridge, oauth, or rebrand behavior Rejected: Broad USER_TYPE cleanup across mixed runtime surfaces | too risky for the next medium-sized PR Confidence: high Scope-risk: moderate Reversibility: clean Directive: The next cleanup pass should continue with similarly isolated USER_TYPE helpers before touching main.tsx or protocol-heavy code Tested: bun run build Tested: bun run smoke Tested: bun run verify:privacy Tested: bun run test:provider Tested: bun run test:provider-recommendation Not-tested: Full repo typecheck (upstream baseline remains noisy) * Align internal-only helper removal with remaining user guidance This follow-up fixes the mock billing stub to be a true no-op and removes stale user-facing references to /verify and /skillify from the same PR. It also leaves a clearer paper trail for review: the deleted verify skill was explicitly ant-gated before removal, and the remaining mock helper callers still resolve to safe no-op returns in the external build. Constraint: Keep the PR focused on consistency fixes and reviewer-requested evidence, not new cleanup scope Rejected: Leave stale guidance for a later PR | would make this branch internally inconsistent after skill removal Confidence: high Scope-risk: narrow Reversibility: clean Directive: When deleting gated features, always sweep user guidance and coordinator prompts in the same pass Tested: bun run build Tested: bun run smoke Tested: bun run verify:privacy Tested: bun run test:provider Tested: bun run test:provider-recommendation Not-tested: Full repo typecheck (upstream baseline remains noisy; changed-file scan still shows only pre-existing tipRegistry errors outside edited lines) * Clarify generic workflow wording after skill removal This removes the last generic verification-skill wording that could still be read as pointing at a deleted bundled command. The guidance now talks about project workflows rather than a specific bundled verify skill. Constraint: Keep the follow-up limited to reviewer-facing wording cleanup on the same PR Rejected: Leave generic wording as-is | still too easy to misread after the explicit /verify references were removed Confidence: high Scope-risk: narrow Reversibility: clean Directive: When removing bundled commands, scrub both explicit and generic references in the same branch Tested: bun run build Tested: bun run smoke Not-tested: Additional checks unchanged by wording-only follow-up --------- Co-authored-by: anandh8x <test@example.com>
* test: stabilize suite and add coverage heatmap * ci: run full bun test suite in pr checks
* security: harden suspicious PR intent scanner * security: reduce pr scanner false positives
## Summary - Extract retry-after header from 429 API errors and include timing guidance in the user-facing error message - Previously, non-quota 429 errors showed a generic message with no guidance on when to retry, only a link to status.anthropic.com ## Impact - user-facing impact: 429 error messages now tell users when to retry instead of just linking to a status page - developer/maintainer impact: none ## Testing - [x] `bun run build` - [ ] `bun run smoke` - [ ] focused tests: error formatting is pure string construction, verified via build + manual inspection ## Notes - provider/model path tested: applies to all providers returning 429 - screenshots attached (if UI changed): n/a - follow-up work or known limitations: 529 errors could get similar treatment in a follow-up https://claude.ai/code/session_01D7kprMn4c66a5WrZscF7rv Co-authored-by: Claude <noreply@anthropic.com>
Reproduction: - Enable `frontend-design@claude-code-plugins` - Enable `frontend-design@claude-plugins-official` - Start OpenClaude with both marketplace plugins active - Both plugins load, but downstream command and skill scopes key off the short plugin name, so both collapse to `frontend-design` and can interfere with interactive startup Fix: - Collapse duplicate marketplace plugins by short name during merge - Keep the enabled copy when enabled state differs; otherwise keep the later config entry - Add regression coverage for both cases
…#242) * security: force lodash-es 4.18.0 for transitive dependencies PR Gitlawb#225 bumped the direct lodash-es dependency to 4.18.0, but @anthropic-ai/sandbox-runtime still pulled lodash-es@4.17.23 via its own ^4.17.23 range. The transitive copy was vulnerable to: - HIGH: Code Injection via _.template (GHSA-r5fr-rjxr-66jc) - MODERATE: Prototype Pollution via _.unset/_.omit (GHSA-f23m-r3pf-42rh) Added overrides field in package.json to force all copies to 4.18.0. bun audit now reports zero vulnerabilities. * fix: use lodash-es 4.18.1 instead of deprecated 4.18.0 lodash-es 4.18.0 is explicitly deprecated by the maintainer with the message "Bad release. Please use lodash-es@4.17.23 instead." Updated both the direct dependency and the override to 4.18.1, which is the latest non-deprecated release that patches the CVEs.
…itlawb#250) Models not in the lookup table fall through to a 200k default, causing auto-compact to never trigger for models with smaller actual context windows. Users hit hard context_window_exceeded errors instead. Added to both context window and max output token tables: - o1, o1-mini, o1-preview, o1-pro (OpenAI reasoning models) - llama3.2:1b, qwen3:8b, codestral (common Ollama models) Relates to Gitlawb#248
…wb#201) * Add local OpenAI-compatible model discovery to /model * Guard local OpenAI model discovery from Codex routing * Preserve remote OpenAI Codex alias behavior
…ls (Gitlawb#241) Models served through Ollama/vLLM with strict Jinja templates (Devstral, Mistral, etc.) require strict user↔assistant role alternation and reject requests with consecutive messages of the same role. convertMessages() could produce consecutive user or assistant messages in three scenarios: batched user input, text-only + tool_use assistant turns, and tool result remainders followed by another user message. Added a coalescing pass at the end of convertMessages() that merges consecutive same-role messages (string concat or array concat), preserving tool_calls on assistant messages. Tool and system messages are excluded from coalescing as they have their own alternation rules. Includes regression tests for both user and assistant coalescing. Fixes Gitlawb#202
* fix: preserve unicode in Windows clipboard fallback * fix: avoid Windows clipboard stdin codepage issues * test: fix Windows clipboard temp path fixture
|
Here are 2 potential solutions i can start with: Solution 1: Tool Deduplication (Recommended)This solution explicitly removes built-in tools that share a name with an overriding MCP tool. This prevents Implementation: const toolPermissionContext = getEmptyToolPermissionContext()
const tools = [...getTools(toolPermissionContext), ...mcpTools]With: const toolPermissionContext = getEmptyToolPermissionContext()
const builtins = getTools(toolPermissionContext)
const mcpToolNames = new Set(mcpTools.map(t => t.name))
const deduplicatedBuiltins = builtins.filter(t => !mcpToolNames.has(t.name))
const tools = [...mcpTools, ...deduplicatedBuiltins](This change must be applied inside both the Solution 2: Reordering the Spread (Simpler, but less robust)If we only care about Implementation: const tools = [...mcpTools, ...getTools(toolPermissionContext)]Pros: One-line fix. Personally, Solution 1 is the correct path forward because it fixes the immediate bug in |
|
lets go with solution 1 then |
|
@MarawanYakout I reviewed this branch locally and I think Solution 1 is the correct fix, not Solution 2. Reordering alone fixes the immediate One additional change is still needed though: in So I'd recommend:
After that, the logic looks good to me. |
|
gnanam1990
left a comment
There was a problem hiding this comment.
Thanks for pushing this forward. I can see the MCP collision follow-up work on the branch, and I agree with the direction of re-exposing connected MCP tools. That said, after taking a deeper look at the current head, I’m still not comfortable approving this PR in its current form for three reasons:
- PR scope is much broader than the stated change
The PR is described as “MCP tool re-exposure & strict input validation,” but the current branch also includes a large number of unrelated changes across gRPC, onboarding, UI, docs, workflow, privacy/tooling, and other areas. That makes it very difficult to review or merge safely as a single unit.
Examples include changes in:
src/grpc/server.tssrc/components/ProviderManager.tsxsrc/components/ThemePicker.tsxdocs/litellm-setup.mdscripts/pr-intent-scan.ts.github/workflows/pr-checks.yml
I think this needs to be narrowed down substantially before it is mergeable.
- “Strict input validation” for re-exposed MCP tools still does not appear to be truly enforced
The current MCP server path still seems to rely on the MCP tool wrapper schema rather than the real upstream MCP schema when validating tool inputs.
Relevant files:
src/entrypoints/mcp.tssrc/services/mcp/client.tssrc/tools/MCPTool/MCPTool.ts
As a result, the branch appears to re-expose MCP tools, but not actually validate arguments strictly against the real remote tool schema in the way the PR description claims.
- Re-exposed MCP tool outputs are still flattened into plain text
In the currentmcp.tspath, tool results are converted into a single text response using either the string result orjsonStringify(finalResult.data). That loses the native structure of upstream MCP tool responses and will break or degrade any non-text or structured MCP result.
Relevant files:
src/entrypoints/mcp.tssrc/services/mcp/client.ts
So even if tool lookup precedence is fixed, the proxy path still looks lossy for richer MCP tools.
I think the MCP re-exposure idea is worth pursuing, but I’d want this PR either:
- split down to just the MCP-specific change, or
- updated so the current branch actually enforces strict upstream MCP schemas and preserves structured MCP outputs
Once that is tightened up, I’d be happy to take another look.
Vasanthdev2004
left a comment
There was a problem hiding this comment.
Rechecked the current head ad6ae12c3089a317d6fb30d7d31b90d12e7461bf against current origin/main.
The earlier no-prefix collision blocker is fixed on this head: MCP tools now win name collisions over builtins via getCombinedTools(...), and the focused tests/build/smoke pass.
I still can't approve because there is another real behavior bug in the new MCP exposure path.
-
src/entrypoints/mcp.ts:79-88
getMcpToolsCommandsAndResources(...)can return synthetic tools for non-connected states, especially the OAuth recovery tool forneeds-authservers (createMcpAuthTool(...)). But this entrypoint only records tools whenclient.type === 'connected':if (client.type === 'connected') { mcpClients.push(client); mcpTools.push(...clientTools) }
That means OAuth-gated MCP servers silently disappear from the re-exposed MCP server instead of surfacing their
...authenticatetool.This is a real regression relative to the intended behavior of
getMcpToolsCommandsAndResources(...)itself, which explicitly emits:client: { type: 'needs-auth', ... }tools: [createMcpAuthTool(name, config)]
So on this branch, a caller can no longer see or invoke the auth/recovery path for a needs-auth MCP server through this MCP entrypoint, even though the lower-level MCP client layer provides it.
Non-blocking note:
- the new
src/entrypoints/mcp.test.tsonly covers builtin-vs-MCP name deduplication. It does not cover the needs-auth path above, which is why this slipped through.
What I verified on this head:
bun test src/entrypoints/mcp.test.ts src/utils/secureStorage/platformStorage.test.ts-> 12 pass- direct runtime repro of MCP precedence:
getCombinedTools([builtin Bash, builtin Read], [MCP Bash])returns MCP Bash first bun run build-> successbun run smoke-> success
I did not find another high-confidence blocker beyond the dropped needs-auth tool path, but I wouldn't merge this until OAuth-gated MCP servers remain visible/authenticatable through the re-exposed MCP surface.
|
@MarawanYakout good job.....! just one step more to reach target |
|
I'm looking into this and theres a lot of touched files? |
|
After going about few things , MCP is very good on my end. 1. OAuth-gated MCP Server Visibility RestoredIssue: 2. Strict Input Validation Enforced via AjvIssue: The proxy path previously relied on the local wrapper schema (
3. Preserved Structured Output for MCP Tool ResultsIssue: Re-exposed MCP tool outputs were being flattened into single plain-text blocks, losing native structures (like distinct Validations Performed
Technically system now upholds strict schema enforcement and full-spectrum MCP transparency while resolving the specific blockers noted in the latest PR review. lets see if there is any other adjustments needed, i am more than happy to adhere. |
|
@kevincodex1 is there something in specific the project needs help in developing ? i can aim my focus towards specific areas of need or importance, tried to contacting on X but couldn't |
Vasanthdev2004
left a comment
There was a problem hiding this comment.
Rechecked the current head b4d424b4f3d393889e588a3c9b1b5390bd704f5c against current origin/main.
Scope
This is a targeted re-review of the current head and the previously-blocked MCP areas, not a full fresh re-review of every historical branch state.
Verdict
Approve-ready
The confusing part here was mostly earlier branch churn and stale review context. On the current head, the actual merge surface is now narrow and coherent again:
src/entrypoints/mcp.tssrc/entrypoints/mcp.test.tssrc/tools/MCPTool/MCPTool.tssrc/utils/secureStorage/platformStorage.test.ts
What I specifically rechecked on this head:
-
No-prefix MCP collisions are fixed
getCombinedTools(...)deduplicates builtins when an MCP tool reuses the same name- MCP tools are ordered ahead of remaining builtins, so
findToolByName(...)resolves the MCP override path correctly
-
Needs-auth / OAuth recovery tools are no longer dropped
loadReexposedMcpTools()now records tools and client contexts regardless of connection state, so theneeds-authrecovery/authenticate path stays visible through the re-exposed MCP surface- there is focused coverage for that behavior in
src/entrypoints/mcp.test.ts
-
The strict-validation / schema-exposure story is now materially better
ListToolsnow preferstool.inputJSONSchema ?? zodToJsonSchema(tool.inputSchema)MCPTool.validateInput()compiles and enforcesinputJSONSchemawith Ajv when present instead of only trusting the passthrough wrapper schema
-
Structured MCP outputs are preserved better than before
- the
CallToolresult mapping now preserves text/image block structure instead of flattening everything into a single text blob by default
- the
-
Checks
smoke-and-testsis green on this head
I’m approving this current shape. The earlier confusion was real, but the branch now looks focused and the previously-blocking MCP behavior issues appear addressed on the current head.
The merge-base changed after approval.
Vasanthdev2004
left a comment
There was a problem hiding this comment.
GitHub auto-dismissed the earlier approval after the merge base changed, so I rechecked the current state.
This is still a targeted re-review of the same head commit b4d424b4f3d393889e588a3c9b1b5390bd704f5c against the updated base, not a new full review from scratch.
I do not see a new blocker from the merge-base movement alone. The approval still stands on the current head:
- MCP/builtin collision handling still looks correct
- needs-auth / OAuth recovery tools are still preserved
- schema exposure + Ajv-backed validation still look correct for this scope
- structured MCP output preservation still looks intact
- checks are still green
So my verdict remains Approve-ready on the current head.
|
@gnanam1990 one more eyes |
|
good work @MarawanYakout |
The merge-base changed after approval.
|
@Vasanthdev2004 @gnanam1990 Thanks guys ! |
|
i'm here if there is any extra adjustments |
|
@kevincodex1 @gnanam1990 @Vasanthdev2004 if guys need help with important issues / pull requests i can help with that too if you guys are working on something challenging or needs collap. |
|
sure @MarawanYakout we will let you know |
|
theres a lot of change files here @Vasanthdev2004 @gnanam1990 |
|
@MarawanYakout can you make a new pr for this fix seems this pr messed up with lot of commits shows 5k line of code change |
|
made a new one @Vasanthdev2004 #675 |
Summary
Tool Re-exposure:
src/entrypoints/mcp.tshas TODOs to re-expose any connected MCP tools back through the server, enabling "Inception-style" tool chainingwhat changed & why it changed:
Import and Initialization (File:
src/entrypoints/mcp.ts)getMcpToolsCommandsAndResources. Add arrays formcpClientsandmcpTools.Load Connections (File:
src/entrypoints/mcp.ts)getMcpToolsCommandsAndResourcesinsidestartMCPServer, pushing eachclientand itstoolsto the arrays.Re-expose Tools (File:
src/entrypoints/mcp.ts)ListToolsRequestSchema, combinegetTools(...)withmcpTools.Execute Tools (File:
src/entrypoints/mcp.ts)CallToolRequestSchema, combinegetTools(...)withmcpToolsforfindToolByName. PassmcpClientsintotoolUseContext.options.mcpClients.toolUseContext.options.mcpClientsto execute the remote call.Impact
Testing
Testing Strategy
npx ecc-agentshield scan .claude mcpoutput if possible.Risks & Mitigations
Risk: Connecting to slow MCP servers delays the
claude mcpstartup.getMcpToolsCommandsAndResourcesruns in parallel with timeouts, so it will bound the startup delay.Risk: Name collisions between native tools and MCP tools.
findToolByNamewill return the first match.bun run buildbun run smoke[ X ] focused tests:
Success Criteria
claude mcploads MCP configurations.ListToolsRequestSchemareturns native + MCP tools.CallToolRequestSchemacan successfully route calls to the connected MCP tools.