Skip to content

feat(mcp): add native /mcp for cost control#4168

Open
alex-alecu wants to merge 1 commit into
mainfrom
feat/native-mcp-dataset-stats
Open

feat(mcp): add native /mcp for cost control#4168
alex-alecu wants to merge 1 commit into
mainfrom
feat/native-mcp-dataset-stats

Conversation

@alex-alecu

Copy link
Copy Markdown
Contributor

Summary

Kilo now has a standard MCP endpoint for admins to read their own Kilo stats without setting custom headers. It uses the normal browser sign-in and OAuth flow, then gives MCP clients one read-only stats tool. Access is limited to Kilo org admins for the first rollout, and each query can only look at the signed-in user's last 60 days.

Verification

  1. Start the web app with MCP gateway keys.
  2. Call /mcp without a token and confirm it returns a 401 OAuth challenge.
  3. Register an MCP client, approve access as a Kilo org admin, exchange the code for a token, then call tools/list.
  4. Call query_kilo_dataset for microdollar_usage with a count metric and confirm it returns a structured result.

Visual Changes

N/A

Reviewer Notes

This adds new OAuth tables and keeps the first rollout behind the Kilo org admin gate. The MCP tool returns aggregate and time series stats only, not raw rows.

@alex-alecu alex-alecu changed the title feat(mcp): add native dataset stats feat(mcp): add native /mcp for cost control Jun 22, 2026
return NextResponse.json({ error: 'invalid_request' }, { status: 400 });
}
const services = createGatewayServices();
if (isNativeMcpResource(parsed.data.resource)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

WARNING: Native refresh-token exchanges are dispatched incorrectly when resource is omitted

OAuthTokenRequestSchema makes resource optional, and the existing gateway token service already handles refresh requests without it. This branch only selects nativeMcpTokenService when the incoming request repeats resource=https://app.kilocode.ai/mcp, so a standards-compliant native refresh request that omits resource will fall through to tokenService.exchangeToken() and fail because the token is looked up in the wrong table.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

const services = createGatewayServices();
try {
return await services.nativeMcpTokenVerifier.verify(token);
} catch {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

WARNING: This collapses authorization failures into 401 invalid_token

verifyNativeMcpBearerToken() distinguishes bad tokens from missing mcp:access and from users who are no longer eligible, but this blanket catch converts every verifier error into the same OAuth challenge. That means a valid token without mcp:access now reports as invalid_token instead of insufficient_scope, and the forbidden path for revoked admin eligibility is hidden from clients too.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

if (type === 'timestamp') return new Date(String(value)).toISOString();
if (type === 'integer') return Number(value);
if (type === 'decimal') return String(value);
if (type === 'boolean') return Boolean(value);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

WARNING: Boolean serialization will invert string-backed Postgres values

tx.execute() can surface booleans as strings such as 't'/'f' or 'true'/'false' depending on the driver/query path. Boolean(value) treats any non-empty string as true, so fields like hasError, repositoryReviewInstructionsUsed, and isRoot can be silently flipped in the MCP response.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

import { GatewayMcpAccessScope } from './types';

export const NativeMcpResourcePath = '/mcp';
export const NativeMcpResourceUrl = 'https://app.kilocode.ai/mcp';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

WARNING: The native MCP resource is hard-coded to production

Every challenge, protected-resource document, JWT aud check, and token claim now binds to https://app.kilocode.ai/mcp even when the app is running under another MCP_GATEWAY_APP_BASE_URL such as preview, staging, or local development. That breaks non-production discovery/token exchange and violates the exact-resource audience contract outside production.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 4 Issues Found | Recommendation: Address before merge

Fix these issues in Kilo Cloud

Overview

Severity Count
CRITICAL 0
WARNING 4
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
apps/web/src/app/api/mcp-gateway/oauth/token/route.ts 35 Native refresh-token requests are misrouted when resource is omitted.
apps/web/src/app/mcp/route.ts 73 Verifier failures are flattened into 401 invalid_token, hiding insufficient_scope and forbidden cases.
apps/web/src/lib/kilo-datasets/query.ts 517 Boolean(value) can flip string-backed Postgres booleans to true.
packages/mcp-gateway/src/native-resource.ts 5 The native MCP resource/audience is hard-coded to production.
Files Reviewed (31 files)
  • .specs/mcp-gateway-auth.md - 0 issues
  • apps/web/package.json - 0 issues
  • apps/web/src/app/.well-known/oauth-authorization-server/oauth/authorize/route.ts - 0 issues
  • apps/web/src/app/.well-known/oauth-authorization-server/route.ts - 0 issues
  • apps/web/src/app/.well-known/oauth-protected-resource/mcp/route.ts - 0 issues
  • apps/web/src/app/.well-known/oauth-protected-resource/route.ts - 0 issues
  • apps/web/src/app/api/mcp-gateway/oauth/authorize/route.test.ts - 0 issues
  • apps/web/src/app/api/mcp-gateway/oauth/authorize/route.ts - 0 issues
  • apps/web/src/app/api/mcp-gateway/oauth/token/route.ts - 1 issue
  • apps/web/src/app/mcp/route.test.ts - 0 issues
  • apps/web/src/app/mcp/route.ts - 1 issue
  • apps/web/src/lib/kilo-datasets/contracts.ts - 0 issues
  • apps/web/src/lib/kilo-datasets/query.test.ts - 0 issues
  • apps/web/src/lib/kilo-datasets/query.ts - 1 issue
  • apps/web/src/lib/mcp-gateway/services.ts - 0 issues
  • apps/web/src/lib/mcp-gateway/token-service.ts - 0 issues
  • apps/web/src/lib/mcp/kilo-dataset-server.ts - 0 issues
  • apps/web/src/lib/native-mcp/oauth/native-authorization-service.ts - 0 issues
  • apps/web/src/lib/native-mcp/oauth/native-token-service.ts - 0 issues
  • apps/web/src/lib/native-mcp/oauth/native-token-verifier.test.ts - 0 issues
  • apps/web/src/lib/native-mcp/oauth/native-token-verifier.ts - 0 issues
  • apps/web/src/lib/user/index.test.ts - 0 issues
  • apps/web/src/lib/user/index.ts - 0 issues
  • packages/db/src/migrations/0167_perpetual_hulk.sql - 0 issues
  • packages/db/src/migrations/meta/0167_snapshot.json - 0 issues
  • packages/db/src/migrations/meta/_journal.json - 0 issues
  • packages/db/src/schema.ts - 0 issues
  • packages/mcp-gateway/src/index.ts - 0 issues
  • packages/mcp-gateway/src/native-resource.ts - 1 issue
  • pnpm-lock.yaml - 0 issues
  • scripts/verify-drizzle-bootstrap.sh - 0 issues

Reviewed by gpt-5.4-20260305 · Input: 181K · Output: 19.9K · Cached: 2.4M

Review guidance: REVIEW.md from base branch main

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