#
tokens: 49695/50000 71/376 files (page 2/25)
lines: off (toggle) GitHub
raw markdown copy
This is page 2 of 25. Use http://codebase.md/cloudflare/mcp-server-cloudflare?page={x} to view the full context.

# Directory Structure

```
├── .changeset
│   ├── config.json
│   └── README.md
├── .dockerignore
├── .editorconfig
├── .eslintrc.cjs
├── .github
│   ├── actions
│   │   └── setup
│   │       └── action.yml
│   ├── ISSUE_TEMPLATE
│   │   └── bug_report.md
│   └── workflows
│       ├── branches.yml
│       ├── main.yml
│       └── release.yml
├── .gitignore
├── .npmrc
├── .prettierignore
├── .prettierrc.cjs
├── .syncpackrc.cjs
├── .vscode
│   ├── extensions.json
│   ├── launch.json
│   ├── settings.json
│   └── tasks.json
├── apps
│   ├── ai-gateway
│   │   ├── .dev.vars.example
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── CONTRIBUTING.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── ai-gateway.app.ts
│   │   │   ├── ai-gateway.context.ts
│   │   │   ├── tools
│   │   │   │   └── ai-gateway.tools.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── auditlogs
│   │   ├── .dev.vars.example
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── auditlogs.app.ts
│   │   │   ├── auditlogs.context.ts
│   │   │   └── tools
│   │   │       └── auditlogs.tools.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── autorag
│   │   ├── .dev.vars.example
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── CONTRIBUTING.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── autorag.app.ts
│   │   │   ├── autorag.context.ts
│   │   │   ├── tools
│   │   │   │   └── autorag.tools.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── browser-rendering
│   │   ├── .dev.vars.example
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── CONTRIBUTING.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── browser.app.ts
│   │   │   ├── browser.context.ts
│   │   │   └── tools
│   │   │       └── browser.tools.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── cloudflare-one-casb
│   │   ├── .dev.vars.example
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── cf1-casb.app.ts
│   │   │   ├── cf1-casb.context.ts
│   │   │   └── tools
│   │   │       └── integrations.tools.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── demo-day
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── frontend
│   │   │   ├── index.html
│   │   │   ├── public
│   │   │   │   ├── anthropic.svg
│   │   │   │   ├── asana.svg
│   │   │   │   ├── atlassian.svg
│   │   │   │   ├── canva.svg
│   │   │   │   ├── cloudflare_logo.svg
│   │   │   │   ├── cloudflare.svg
│   │   │   │   ├── dina.jpg
│   │   │   │   ├── favicon-16x16.png
│   │   │   │   ├── favicon-32x32.png
│   │   │   │   ├── favicon.ico
│   │   │   │   ├── favicon.png
│   │   │   │   ├── intercom.svg
│   │   │   │   ├── linear.svg
│   │   │   │   ├── matt.jpg
│   │   │   │   ├── mcp_demo_day.svg
│   │   │   │   ├── mcpog.png
│   │   │   │   ├── more.svg
│   │   │   │   ├── paypal.svg
│   │   │   │   ├── pete.jpeg
│   │   │   │   ├── sentry.svg
│   │   │   │   ├── special_guest.png
│   │   │   │   ├── square.svg
│   │   │   │   ├── stripe.svg
│   │   │   │   ├── sunil.jpg
│   │   │   │   └── webflow.svg
│   │   │   ├── script.js
│   │   │   └── styles.css
│   │   ├── package.json
│   │   ├── src
│   │   │   └── demo-day.app.ts
│   │   ├── tsconfig.json
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.json
│   ├── dex-analysis
│   │   ├── .dev.vars.example
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── dex-analysis.app.ts
│   │   │   ├── dex-analysis.context.ts
│   │   │   ├── tools
│   │   │   │   └── dex-analysis.tools.ts
│   │   │   └── warp_diag_reader.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── dns-analytics
│   │   ├── .dev.vars.example
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── CONTRIBUTING.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── dns-analytics.app.ts
│   │   │   ├── dns-analytics.context.ts
│   │   │   └── tools
│   │   │       └── dex-analytics.tools.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── docs-autorag
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── docs-autorag.app.ts
│   │   │   ├── docs-autorag.context.ts
│   │   │   └── tools
│   │   │       └── docs-autorag.tools.ts
│   │   ├── tsconfig.json
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── docs-vectorize
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── docs-vectorize.app.ts
│   │   │   └── docs-vectorize.context.ts
│   │   ├── tsconfig.json
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── graphql
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── graphql.app.ts
│   │   │   ├── graphql.context.ts
│   │   │   └── tools
│   │   │       └── graphql.tools.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── logpush
│   │   ├── .dev.vars.example
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── logpush.app.ts
│   │   │   ├── logpush.context.ts
│   │   │   └── tools
│   │   │       └── logpush.tools.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── radar
│   │   ├── .dev.vars.example
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── CONTRIBUTING.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── radar.app.ts
│   │   │   ├── radar.context.ts
│   │   │   ├── tools
│   │   │   │   ├── radar.tools.ts
│   │   │   │   └── url-scanner.tools.ts
│   │   │   ├── types
│   │   │   │   ├── radar.ts
│   │   │   │   └── url-scanner.ts
│   │   │   └── utils.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── sandbox-container
│   │   ├── .dev.vars.example
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── container
│   │   │   ├── fileUtils.spec.ts
│   │   │   ├── fileUtils.ts
│   │   │   ├── sandbox.container.app.ts
│   │   │   └── tsconfig.json
│   │   ├── CONTRIBUTING.md
│   │   ├── Dockerfile
│   │   ├── evals
│   │   │   ├── exec.eval.ts
│   │   │   ├── files.eval.ts
│   │   │   ├── initialize.eval.ts
│   │   │   └── utils.ts
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── server
│   │   │   ├── containerHelpers.ts
│   │   │   ├── containerManager.ts
│   │   │   ├── containerMcp.ts
│   │   │   ├── metrics.ts
│   │   │   ├── prompts.ts
│   │   │   ├── sandbox.server.app.ts
│   │   │   ├── sandbox.server.context.ts
│   │   │   ├── userContainer.ts
│   │   │   ├── utils.spec.ts
│   │   │   └── utils.ts
│   │   ├── shared
│   │   │   ├── consts.ts
│   │   │   └── schema.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── vitest.config.evals.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── workers-bindings
│   │   ├── .dev.vars.example
│   │   ├── .eslintrc.cjs
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── CONTRIBUTING.md
│   │   ├── evals
│   │   │   ├── accounts.eval.ts
│   │   │   ├── hyperdrive.eval.ts
│   │   │   ├── kv_namespaces.eval.ts
│   │   │   ├── types.d.ts
│   │   │   └── utils.ts
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── bindings.app.ts
│   │   │   └── bindings.context.ts
│   │   ├── tsconfig.json
│   │   ├── vitest.config.evals.ts
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   ├── workers-builds
│   │   ├── .dev.vars.example
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── CONTRIBUTING.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── tools
│   │   │   │   └── workers-builds.tools.ts
│   │   │   ├── workers-builds.app.ts
│   │   │   └── workers-builds.context.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── vite.config.mts
│   │   ├── vitest.config.ts
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.jsonc
│   └── workers-observability
│       ├── .dev.vars.example
│       ├── .eslintrc.cjs
│       ├── CHANGELOG.md
│       ├── CONTRIBUTING.md
│       ├── package.json
│       ├── README.md
│       ├── src
│       │   ├── tools
│       │   │   └── workers-observability.tools.ts
│       │   ├── workers-observability.app.ts
│       │   └── workers-observability.context.ts
│       ├── tsconfig.json
│       ├── types.d.ts
│       ├── vitest.config.ts
│       ├── worker-configuration.d.ts
│       └── wrangler.jsonc
├── CONTRIBUTING.md
├── implementation-guides
│   ├── evals.md
│   ├── tools.md
│   └── type-validators.md
├── LICENSE
├── package.json
├── packages
│   ├── eslint-config
│   │   ├── CHANGELOG.md
│   │   ├── default.cjs
│   │   ├── package.json
│   │   └── README.md
│   ├── eval-tools
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── src
│   │   │   ├── runTask.ts
│   │   │   ├── scorers.ts
│   │   │   └── test-models.ts
│   │   ├── tsconfig.json
│   │   ├── worker-configuration.d.ts
│   │   └── wrangler.json
│   ├── mcp-common
│   │   ├── .eslintrc.cjs
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── api
│   │   │   │   ├── account.api.ts
│   │   │   │   ├── cf1-integration.api.ts
│   │   │   │   ├── workers-builds.api.ts
│   │   │   │   ├── workers-observability.api.ts
│   │   │   │   ├── workers.api.ts
│   │   │   │   └── zone.api.ts
│   │   │   ├── api-handler.ts
│   │   │   ├── api-token-mode.ts
│   │   │   ├── cloudflare-api.ts
│   │   │   ├── cloudflare-auth.ts
│   │   │   ├── cloudflare-oauth-handler.ts
│   │   │   ├── config.ts
│   │   │   ├── constants.ts
│   │   │   ├── durable-kv-store.ts
│   │   │   ├── durable-objects
│   │   │   │   └── user_details.do.ts
│   │   │   ├── env.ts
│   │   │   ├── format.spec.ts
│   │   │   ├── format.ts
│   │   │   ├── get-props.ts
│   │   │   ├── mcp-error.ts
│   │   │   ├── poll.ts
│   │   │   ├── prompts
│   │   │   │   └── docs-vectorize.prompts.ts
│   │   │   ├── scopes.ts
│   │   │   ├── sentry.ts
│   │   │   ├── server.ts
│   │   │   ├── tools
│   │   │   │   ├── account.tools.ts
│   │   │   │   ├── d1.tools.ts
│   │   │   │   ├── docs-vectorize.tools.ts
│   │   │   │   ├── hyperdrive.tools.ts
│   │   │   │   ├── kv_namespace.tools.ts
│   │   │   │   ├── r2_bucket.tools.ts
│   │   │   │   ├── worker.tools.ts
│   │   │   │   └── zone.tools.ts
│   │   │   ├── types
│   │   │   │   ├── cf1-integrations.types.ts
│   │   │   │   ├── cloudflare-mcp-agent.types.ts
│   │   │   │   ├── d1.types.ts
│   │   │   │   ├── hyperdrive.types.ts
│   │   │   │   ├── kv_namespace.types.ts
│   │   │   │   ├── r2_bucket.types.ts
│   │   │   │   ├── shared.types.ts
│   │   │   │   ├── tools.types.ts
│   │   │   │   ├── workers-builds.types.ts
│   │   │   │   ├── workers-logs.types.ts
│   │   │   │   └── workers.types.ts
│   │   │   ├── utils.spec.ts
│   │   │   ├── utils.ts
│   │   │   └── v4-api.ts
│   │   ├── tests
│   │   │   └── utils
│   │   │       └── cloudflare-mock.ts
│   │   ├── tsconfig.json
│   │   ├── types.d.ts
│   │   ├── vitest.config.ts
│   │   └── worker-configuration.d.ts
│   ├── mcp-observability
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── src
│   │   │   ├── analytics-engine.ts
│   │   │   ├── index.ts
│   │   │   └── metrics.ts
│   │   ├── tsconfig.json
│   │   └── worker-configuration.d.ts
│   ├── tools
│   │   ├── .eslintrc.cjs
│   │   ├── bin
│   │   │   ├── run-changeset-new
│   │   │   ├── run-eslint-workers
│   │   │   ├── run-fix-deps
│   │   │   ├── run-tsc
│   │   │   ├── run-turbo
│   │   │   ├── run-vitest
│   │   │   ├── run-vitest-ci
│   │   │   ├── run-wrangler-deploy
│   │   │   ├── run-wrangler-types
│   │   │   └── runx
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── bin
│   │   │   │   └── runx.ts
│   │   │   ├── changesets.spec.ts
│   │   │   ├── changesets.ts
│   │   │   ├── cmd
│   │   │   │   └── deploy-published-packages.ts
│   │   │   ├── proc.ts
│   │   │   ├── test
│   │   │   │   ├── fixtures
│   │   │   │   │   └── changesets
│   │   │   │   │       ├── empty
│   │   │   │   │       │   └── .gitkeep
│   │   │   │   │       ├── invalid-json
│   │   │   │   │       │   └── published-packages.json
│   │   │   │   │       ├── invalid-schema
│   │   │   │   │       │   └── published-packages.json
│   │   │   │   │       └── valid
│   │   │   │   │           └── published-packages.json
│   │   │   │   └── setup.ts
│   │   │   └── tsconfig.ts
│   │   ├── tsconfig.json
│   │   └── vitest.config.ts
│   └── typescript-config
│       ├── CHANGELOG.md
│       ├── package.json
│       ├── tools.json
│       ├── workers-lib.json
│       └── workers.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── README.md
├── server.json
├── tsconfig.json
├── turbo.json
└── vitest.workspace.ts
```

# Files

--------------------------------------------------------------------------------
/apps/sandbox-container/shared/schema.ts:
--------------------------------------------------------------------------------

```typescript
import z from 'zod'

export type ExecParams = z.infer<typeof ExecParams>
export const ExecParams = z.object({
	args: z.string(),
	timeout: z.number().optional().describe('Timeout in milliseconds'),
	streamStderr: z.boolean().default(true),
})

export type FileWrite = z.infer<typeof FileWrite>
export const FileWrite = z.object({
	path: z.string(),
	text: z.string().describe('Full text content of the file you want to write.'),
})

export type FilePathParam = z.infer<typeof FilePathParam>
export const FilePathParam = z.object({
	path: z.string(),
})

export type FileList = z.infer<typeof FileList>
export const FileList = z.object({
	resources: z
		.object({
			uri: z.string(),
			name: z.string(),
			description: z.string().optional(),
			mimeType: z.string().optional(),
		})
		.array(),
})

export type FilesContextSchema = z.infer<typeof FilesContextSchema>
export const FilesContextSchema = z.object({
	files: z
		.object({
			uri: z.string(),
		})
		.array(),
})

```

--------------------------------------------------------------------------------
/apps/demo-day/wrangler.json:
--------------------------------------------------------------------------------

```json
{
	"$schema": "node_modules/wrangler/config-schema.json",
	"main": "src/demo-day.app.ts",
	"compatibility_date": "2025-03-10",
	"compatibility_flags": ["nodejs_compat"],
	"account_id": "6702657b6aa048cf3081ff3ff3c9c52f",
	"routes": [{ "pattern": "demo-day.mcp.cloudflare.com", "custom_domain": true }],
	"name": "mcp-cloudflare-demo-day",
	"migrations": [
		{
			"new_sqlite_classes": ["CloudflareDemoDayMCP"],
			"tag": "v1"
		}
	],
	"observability": {
		"enabled": true
	},
	"durable_objects": {
		"bindings": [
			{
				"class_name": "CloudflareDemoDayMCP",
				"name": "MCP_OBJECT"
			}
		]
	},
	"assets": {
		"directory": "./frontend",
		"binding": "ASSETS"
	},
	"vars": {
		"ENVIRONMENT": "development",
		"MCP_SERVER_NAME": "PLACEHOLDER",
		"MCP_SERVER_VERSION": "PLACEHOLDER"
	},
	"dev": {
		"port": 8976
	},
	"workers_dev": false,
	"preview_urls": false,
	"analytics_engine_datasets": [
		{
			"binding": "MCP_METRICS",
			"dataset": "mcp-metrics-production"
		}
	]
}

```

--------------------------------------------------------------------------------
/apps/ai-gateway/src/types.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from 'zod'

export const GatewayIdParam = z.string().describe('The gateway ID.')
export const LogIdParam = z.string()
export const pageParam = z.number().int().min(1).optional().default(1)
export const perPageParam = z.number().int().min(1).max(50).optional().default(20)

export const ListLogsParams = {
	gateway_id: GatewayIdParam,
	page: pageParam,
	per_page: perPageParam,
	order_by: z
		.enum([
			'created_at',
			'provider',
			'model',
			'model_type',
			'success',
			'cached',
			'cost',
			'tokens_in',
			'tokens_out',
			'duration',
			'feedback',
		])
		.optional()
		.default('created_at'),
	order_by_direction: z.enum(['asc', 'desc']).optional().default('desc'),
	start_date: z.string().datetime().optional(),
	end_date: z.string().datetime().optional(),
	feedback: z.union([z.literal(-1), z.literal(0), z.literal(1)]).optional(),
	success: z.boolean().optional(),
	cached: z.boolean().optional(),
	model: z.string().toLowerCase().optional(),
	provider: z.string().toLowerCase().optional(),
}

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/utils.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Utility functions for common operations
 */

/**
 * Parse a relative time string into seconds
 */
export function parseRelativeTime(input: string): number {
	const units = { s: 1, m: 60, h: 3600, d: 86400, w: 604800 } as const

	const cleanedInput = input.replace(/\s+/g, '').toLowerCase()
	if (!/^[+-](?:\d+[smhdw]){1,}$/.test(cleanedInput)) {
		throw new Error(`Invalid relative time format: ${input}`)
	}

	const sign = cleanedInput.startsWith('-') ? -1 : 1

	const timeStr = cleanedInput.slice(1) // Remove the sign
	const matches = timeStr.match(/\d+[smhdw]/g)

	if (!matches) {
		throw new Error(`No matches found while parsing relative time: ${timeStr}`)
	}

	const seconds = matches.reduce((total, match) => {
		const value = parseInt(match)
		const unit = match.slice(-1) as keyof typeof units

		return total + value * units[unit]
	}, 0)

	return sign * seconds
}

/**
 * Get the current time as an ISO string without milliseconds
 */
export function nowISO(): string {
	return new Date().toISOString().split('.')[0] + 'Z'
}

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/utils.spec.ts:
--------------------------------------------------------------------------------

```typescript
import { describe, expect, it } from 'vitest'

import { nowISO, parseRelativeTime } from './utils'

describe('parseRelativeTime', () => {
	it('parses positive relative time correctly', () => {
		expect(parseRelativeTime('+1h')).toBe(3600)
		expect(parseRelativeTime('+2d')).toBe(172800)
		expect(parseRelativeTime('+3w')).toBe(1814400)
	})

	it('parses negative relative time correctly', () => {
		expect(parseRelativeTime('-1h')).toBe(-3600)
		expect(parseRelativeTime('-2d')).toBe(-172800)
		expect(parseRelativeTime('-3w')).toBe(-1814400)
	})

	it('parses mixed units correctly', () => {
		expect(parseRelativeTime('+1h30m')).toBe(5400)
		expect(parseRelativeTime('-2d6h')).toBe(-194400)
	})

	it('throws an error for invalid formats', () => {
		expect(() => parseRelativeTime('1h')).toThrow()
		expect(() => parseRelativeTime('+')).toThrow()
		expect(() => parseRelativeTime('')).toThrow()
	})
})

describe('nowISO', () => {
	it('returns the current time in ISO format without milliseconds', () => {
		const isoRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/
		expect(nowISO()).toMatch(isoRegex)
	})
})

```

--------------------------------------------------------------------------------
/apps/sandbox-container/container/fileUtils.ts:
--------------------------------------------------------------------------------

```typescript
import * as fs from 'node:fs/promises'
import path from 'node:path'
import mime from 'mime'

// this is because there isn't a "real" directory mime type, so we're reusing the "text/directory" mime type
// so claude doesn't give an error
export const DIRECTORY_CONTENT_TYPE = 'text/directory'

export async function get_file_name_from_path(path: string): Promise<string> {
	path = path.replace('/files/contents', '')
	path = path.endsWith('/') ? path.substring(0, path.length - 1) : path

	return path
}

export async function list_files_in_directory(dirPath: string): Promise<string[]> {
	const files: string[] = []
	try {
		const dir = await fs.readdir(path.join(process.cwd(), dirPath), {
			withFileTypes: true,
		})
		for (const dirent of dir) {
			const relPath = path.relative(process.cwd(), `${dirPath}/${dirent.name}`)
			files.push(`file:///${relPath}`)
		}
	} catch (error) {
		throw new Error('Failed to read directory')
	}

	return files
}

export async function get_mime_type(path: string): Promise<string | null> {
	let mimeType = mime.getType(path)
	if (mimeType && mimeType === 'inode/directory') {
		mimeType = DIRECTORY_CONTENT_TYPE
	}
	return mimeType
}

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/api/zone.api.ts:
--------------------------------------------------------------------------------

```typescript
import type { Cloudflare } from 'cloudflare'

export interface ZoneListParams {
	client: Cloudflare
	accountId: string
	page?: number
	perPage?: number
	direction?: 'asc' | 'desc'
	match?: 'any' | 'all'
	name?: string
	status?: string
	order?: string
}

/**
 * Lists zones under a Cloudflare account
 * @see https://developers.cloudflare.com/api/resources/zones/methods/list/
 */
export async function handleZonesList({
	client,
	accountId,
	page = 1,
	perPage = 50,
	direction = 'desc',
	match = 'all',
	name,
	status,
	order = 'name',
}: ZoneListParams) {
	// Build query parameters
	const query: Record<string, string | number> = {
		page,
		per_page: perPage,
		direction,
		match,
		account_id: accountId,
	}

	// Only add these parameters if they're defined and not empty strings
	if (name) {
		query.name = name
	}

	if (status) {
		query.status = status
	}

	if (order) {
		query.order = order
	}

	try {
		// Use the zones.list method from the Cloudflare client
		const response = await client.zones.list({ query })
		return response.result
	} catch (error) {
		throw new Error(
			`Failed to list zones: ${error instanceof Error ? error.message : String(error)}`
		)
	}
}

```

--------------------------------------------------------------------------------
/apps/demo-day/frontend/public/linear.svg:
--------------------------------------------------------------------------------

```
<svg viewBox="0 0 360 360" xmlns="http://www.w3.org/2000/svg">
  <path d="M191.137 358.995C190.409 359.041 189.692 358.767 189.168 358.243L1.75637 170.832C1.23337 170.309 0.959476 169.592 1.00488 168.863C1.53318 160.381 2.65162 152.059 4.31955 143.937C4.71808 141.997 7.11977 141.275 8.56629 142.722L217.278 351.434C218.725 352.88 218.003 355.282 216.063 355.68C207.941 357.348 199.619 358.467 191.137 358.995Z
  M271.681 330.339C272.867 331.525 272.629 333.48 271.218 334.319C265.245 337.867 259.048 341.079 252.654 343.927C251.693 344.355 250.562 344.14 249.808 343.386L16.6141 110.192C15.8595 109.438 15.6451 108.307 16.0728 107.346C18.9209 100.952 22.1325 94.7553 25.6814 88.7824C26.5198 87.3714 28.4748 87.1327 29.6613 88.3192L271.681 330.339Z
  M299.142 313.842C298.141 314.736 296.606 314.687 295.64 313.721L46.2784 64.3593C45.3129 63.3937 45.2633 61.859 46.1577 60.8578C78.9703 24.1231 126.698 1 179.827 1C278.781 1 359 81.2185 359 180.173C359 233.302 335.877 281.03 299.142 313.842Z
  M5.38505 221.254C4.83372 218.903 7.62147 217.274 9.45134 219.104L140.896 350.548C142.726 352.378 141.097 355.166 138.746 354.615C72.7835 339.141 20.8589 287.216 5.38505 221.254Z" 
  fill="none" stroke="white" stroke-width="1"/>
</svg>
```

--------------------------------------------------------------------------------
/packages/mcp-common/src/durable-objects/user_details.do.ts:
--------------------------------------------------------------------------------

```typescript
import { DurableObject } from 'cloudflare:workers'
import { z } from 'zod'

import { DurableKVStore } from '../durable-kv-store'

import type { DurableKVStorageKeys } from '../durable-kv-store'

// Durable Object for persisting UserDetails in DO storage across sessions based off the userId
export class UserDetails extends DurableObject {
	private readonly kv: DurableKVStore<UserDetailsKeys>
	constructor(state: DurableObjectState, env: unknown) {
		super(state, env)
		this.env = env
		this.kv = new DurableKVStore({
			state,
			prefix: 'meta',
			keys: UserDetailsKeys,
		})
	}

	public async getActiveAccountId() {
		return await this.kv.get('active_account_id')
	}

	public async setActiveAccountId(activeAccountId: string) {
		this.kv.put('active_account_id', activeAccountId)
	}
}

/**
 * Storage keys used by UserDetails
 */
type UserDetailsKeys = typeof UserDetailsKeys
const UserDetailsKeys = {
	active_account_id: z.string(),
} as const satisfies DurableKVStorageKeys

/** Get the UserDetails instance */
export function getUserDetails(
	env: { USER_DETAILS: DurableObjectNamespace<UserDetails> },
	user_id: string
): DurableObjectStub<UserDetails> {
	const id = env.USER_DETAILS.idFromName(user_id)
	return env.USER_DETAILS.get(id)
}

```

--------------------------------------------------------------------------------
/apps/sandbox-container/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
# Use Alpine as base for minimal size
FROM alpine:3.19 as base

# Install necessary packages while minimizing layers
# We combine commands with && and clean cache in the same layer
# to reduce the image size
RUN apk update && \
    apk add --no-cache \
    # Core utilities
    git \
    curl \
    wget \
    # Build essentials
    build-base \
    # Python and pip
    python3 \
    py3-pip \
    # Node and npm
    nodejs \
    npm && \
    # Clean up the cache to reduce image size
    rm -rf /var/cache/apk/* && \
    # Create symlink for python
    ln -sf /usr/bin/python3 /usr/bin/python

# Install pnpm in a separate layer for better caching
RUN npm install -g pnpm && \
    rm -rf /root/.npm

# Set up pnpm environment
ENV PNPM_HOME=/usr/local/bin
ENV PATH=$PNPM_HOME:$PATH

# Set working directory
WORKDIR /app

# Set environment variables
ENV PATH="/app/node_modules/.bin:${PATH}"

###
# STAGE: PRUNE -  Generate a partial monorepo for the sandbox-container app. The output will be placed into a directory named "out"
###
FROM base AS prune
WORKDIR /app
RUN pnpm install turbo --global
COPY . .
RUN turbo prune containers-starter

###
# STAGE: INSTALL & RUN
###
FROM base AS installer
WORKDIR /app

COPY --from=prune /app/out/ .
RUN pnpm install --frozen-lockfile --only=production

WORKDIR /app/apps/sandbox-container

# Expose the port your Node.js server will run on
EXPOSE 8080

CMD ["pnpm", "run", "start:container"]

```

--------------------------------------------------------------------------------
/apps/docs-vectorize/src/docs-vectorize.app.ts:
--------------------------------------------------------------------------------

```typescript
import { McpAgent } from 'agents/mcp'

import { createApiHandler } from '@repo/mcp-common/src/api-handler'
import { getEnv } from '@repo/mcp-common/src/env'
import { registerPrompts } from '@repo/mcp-common/src/prompts/docs-vectorize.prompts'
import { initSentry } from '@repo/mcp-common/src/sentry'
import { CloudflareMCPServer } from '@repo/mcp-common/src/server'
import { registerDocsTools } from '@repo/mcp-common/src/tools/docs-vectorize.tools'

import type { Env } from './docs-vectorize.context'

const env = getEnv<Env>()

// The docs MCP server isn't stateful, so we don't have state/props
export type Props = never

export type State = never

export class CloudflareDocumentationMCP extends McpAgent<Env, State, Props> {
	_server: CloudflareMCPServer | undefined
	set server(server: CloudflareMCPServer) {
		this._server = server
	}
	get server(): CloudflareMCPServer {
		if (!this._server) {
			throw new Error('Tried to access server before it was initialized')
		}

		return this._server
	}

	constructor(
		public ctx: DurableObjectState,
		public env: Env
	) {
		super(ctx, env)
	}

	async init() {
		const sentry = initSentry(env, this.ctx)

		this.server = new CloudflareMCPServer({
			wae: env.MCP_METRICS,
			serverInfo: {
				name: env.MCP_SERVER_NAME,
				version: env.MCP_SERVER_VERSION,
			},
			sentry,
		})

		registerDocsTools(this, this.env)
		registerPrompts(this)
	}
}

export default createApiHandler(CloudflareDocumentationMCP)

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/api/account.api.ts:
--------------------------------------------------------------------------------

```typescript
import { getProps } from '../get-props'

import type { Cloudflare } from 'cloudflare'
import type { Account } from 'cloudflare/resources/accounts/accounts.mjs'
import type { CloudflareMcpAgent } from '../types/cloudflare-mcp-agent.types'
import type { ToolHandler } from '../types/tools.types'

export async function handleAccountsList({ client }: { client: Cloudflare }): Promise<Account[]> {
	// Currently limited to 50 accounts
	const response = await client.accounts.list({ query: { per_page: 50 } })
	return response.result
}

export const withAccountCheck = <T extends Record<string, any>>(
	agent: CloudflareMcpAgent,
	handler: ToolHandler<T>
) => {
	return async (params: T) => {
		const accountId = await agent.getActiveAccountId()
		if (!accountId) {
			return {
				content: [
					{
						type: 'text' as const,
						text: 'No currently active accountId. Try listing your accounts (accounts_list) and then setting an active account (set_active_account)',
					},
				],
			}
		}

		try {
			const props = getProps(agent)
			const result = await handler({
				...params,
				accountId,
				apiToken: props.accessToken || '',
			})
			return {
				content: [{ type: 'text' as const, text: JSON.stringify(result) }],
			}
		} catch (error) {
			return {
				content: [
					{
						type: 'text' as const,
						text: JSON.stringify({
							error: `Error processing request: ${error instanceof Error ? error.message : 'Unknown error'}`,
						}),
					},
				],
			}
		}
	}
}

```

--------------------------------------------------------------------------------
/apps/demo-day/frontend/public/paypal.svg:
--------------------------------------------------------------------------------

```

<svg viewBox="0 0 296 360" fill="none" xmlns="http://www.w3.org/2000/svg">
  <!-- First P shape -->
  <path d="M44.878 13.781C45.961 6.951 51.837 1.918 58.738 1.918H163.79C199.909 1.918 227.809 9.575 243.174 27.105C250.189 35.11 254.697 43.501 256.956 53.124C259.138 62.42 259.232 72.918 257.396 85.401C254.193 83.784 250.755 82.382 247.104 81.16C246.068 80.817 245.019 80.495 243.954 80.184C241.821 79.56 239.621 78.993 237.356 78.492C235.091 77.981 232.761 77.537 230.36 77.151C221.985 75.801 212.834 75.162 203.04 75.162H120.688C118.516 75.162 116.443 75.656 114.583 76.542C110.497 78.508 107.458 82.386 106.714 87.122L73.057 300.893H9.053C4.134 300.893 0.367 296.49 1.14 291.609L44.878 13.781Z" stroke="white" stroke-width="1"/>
  
  <!-- Second P shape -->
  <path d="M256.119 92.901C249.235 128.32 234.037 152.041 213.136 166.928C192.214 181.831 165.458 187.966 135.312 187.966H104.486C96.593 187.966 89.933 193.724 88.707 201.519L68.447 330.168C67.594 335.567 71.763 340.464 77.223 340.464H131.89C138.849 340.464 144.769 335.392 145.862 328.52L146.392 325.745L146.398 325.713L156.699 260.324L157.36 256.721L157.365 256.697C158.298 250.785 163.387 246.425 169.364 246.425H177.545C204.147 246.425 227.981 241.014 246.709 227.676C265.458 214.322 278.968 193.108 285.065 161.747C290.15 135.571 287.572 113.448 273.897 97.837C269.747 93.106 264.606 89.214 258.645 86.048L257.407 85.39L257.188 86.775C256.871 88.781 256.528 90.81 256.119 92.901Z" stroke="white" stroke-width="1"/>
</svg>
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
	"name": "@cloudflare/mcp-server-cloudflare",
	"version": "1.0.0",
	"description": "Monorepo for Cloudflare MCP servers",
	"private": true,
	"license": "Apache-2.0",
	"author": "Cloudflare, Inc. (https://cloudflare.com)",
	"homepage": "https://github.com/cloudflare/mcp-server-cloudflare",
	"bugs": "https://github.com/cloudflare/mcp-server-cloudflare/issues",
	"type": "module",
	"sideEffects": false,
	"scripts": {
		"changeset:new": "run-changeset-new",
		"check:deps": "syncpack lint",
		"check:format": "prettier . --check --cache --ignore-unknown",
		"check:turbo": "run-turbo check",
		"types": "run-turbo types",
		"test:ci": "run-vitest-ci",
		"test": "vitest run --passWithNoTests",
		"fix:format": "prettier . --write --cache --ignore-unknown",
		"fix:deps": "run-fix-deps",
		"test:watch": "vitest",
		"eval:ci": "run-turbo eval:ci",
		"eval:dev": "run-turbo eval:dev",
		"update-deps": "syncpack update"
	},
	"devDependencies": {
		"@changesets/cli": "2.28.1",
		"@cloudflare/vitest-pool-workers": "0.8.14",
		"@ianvs/prettier-plugin-sort-imports": "4.4.1",
		"@repo/eslint-config": "workspace:*",
		"@repo/tools": "workspace:*",
		"@repo/typescript-config": "workspace:*",
		"@vitest/ui": "3.0.9",
		"prettier": "3.5.3",
		"syncpack": "13.0.3",
		"turbo": "2.5.0",
		"typescript": "5.5.4",
		"vitest": "3.0.9"
	},
	"packageManager": "[email protected]",
	"pnpm": {
		"onlyBuiltDependencies": [
			"esbuild",
			"sharp",
			"workerd"
		],
		"overrides": {
			"esbuild": "0.25.1"
		}
	}
}

```

--------------------------------------------------------------------------------
/apps/sandbox-container/evals/exec.eval.ts:
--------------------------------------------------------------------------------

```typescript
import { expect } from 'vitest'
import { describeEval } from 'vitest-evals'

import { runTask } from '@repo/eval-tools/src/runTask'
import { checkFactuality } from '@repo/eval-tools/src/scorers'
import { eachModel } from '@repo/eval-tools/src/test-models'

import { initializeClient } from './utils'

eachModel('$modelName', ({ model }) => {
	describeEval('Runs a python file in a container', {
		data: async () => [
			{
				input: 'Create a hello world python script and run it',
				expected: `The container_file_write tool was called, containing a file ending in .py.\
				Then the container_file_exec tool was called with python or python3 as one of the arguments`,
			},
		],
		task: async (input) => {
			const client = await initializeClient()
			const { promptOutput, toolCalls } = await runTask(client, model, input)

			expect(toolCalls).toEqual(
				expect.arrayContaining([
					expect.objectContaining({
						type: 'tool-call',
						toolName: 'container_exec',
						args: {
							args: expect.objectContaining({
								args: expect.stringContaining('python'),
							}),
						},
					}),
				])
			)

			expect(toolCalls).toEqual(
				expect.arrayContaining([
					expect.objectContaining({
						type: 'tool-call',
						toolName: 'container_file_write',
						args: {
							args: expect.objectContaining({
								path: expect.stringContaining('.py'),
							}),
						},
					}),
				])
			)

			return promptOutput
		},
		scorers: [checkFactuality],
		threshold: 1,
		timeout: 60000,
	})
})

```

--------------------------------------------------------------------------------
/packages/mcp-common/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# @repo/mcp-common

## 0.19.3

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]

## 0.19.2

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools

## 0.19.1

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]

## 0.19.0

### Minor Changes

- 1833c6d: add relative timeframe support for querying

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [cc6d41f]
  - @repo/[email protected]

## 0.18.0

### Minor Changes

- f885d07: Add search docs tool to bindings and obs servers

## 0.17.1

### Patch Changes

- 83e2d19: Pass in type user_token in props during oauth flow

## 0.17.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]

## 0.16.3

### Patch Changes

- 3677a18: Remove extraneous log

## 0.16.2

### Patch Changes

- 86c2e4f: Add API token passthrough auth

## 0.16.1

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/graphql/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# graphql-mcp-server

## 0.1.6

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.5

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/workers-bindings/package.json:
--------------------------------------------------------------------------------

```json
{
	"name": "workers-bindings",
	"version": "0.4.1",
	"private": true,
	"scripts": {
		"check:lint": "run-eslint-workers",
		"check:types": "run-tsc",
		"deploy": "run-wrangler-deploy",
		"deploy:staging": "wrangler deploy --env staging",
		"deploy:production": "wrangler deploy --env production",
		"eval:dev": "start-server-and-test --expect 404 eval:server http://localhost:8977 'vitest --testTimeout=60000 --config vitest.config.evals.ts'",
		"eval:server": "wrangler dev --var ENVIRONMENT:test --var DEV_DISABLE_OAUTH:true --var DEV_CLOUDFLARE_EMAIL:[email protected] --inspector-port 9230 --port 8977",
		"eval:ci": "start-server-and-test --expect 404 eval:server http://localhost:8977 'vitest run --testTimeout=60000 --config vitest.config.evals.ts'",
		"dev": "wrangler dev",
		"start": "wrangler dev",
		"types": "wrangler types --include-env=false",
		"test": "vitest"
	},
	"devDependencies": {
		"@cloudflare/vitest-pool-workers": "0.8.14",
		"@types/node": "22.14.1",
		"marked": "15.0.7",
		"typescript": "5.5.4",
		"vitest": "3.0.9",
		"wrangler": "4.10.0"
	},
	"dependencies": {
		"@cloudflare/workers-oauth-provider": "0.0.5",
		"@modelcontextprotocol/sdk": "1.18.2",
		"@n8n/json-schema-to-zod": "1.1.0",
		"@repo/eval-tools": "workspace:*",
		"@repo/mcp-common": "workspace:*",
		"@repo/mcp-observability": "workspace:*",
		"agents": "0.2.7",
		"ai": "4.3.10",
		"concurrently": "9.1.2",
		"hono": "4.7.6",
		"start-server-and-test": "2.0.11",
		"vitest-evals": "0.1.4",
		"zod": "3.24.2"
	}
}

```

--------------------------------------------------------------------------------
/packages/tools/src/changesets.ts:
--------------------------------------------------------------------------------

```typescript
import { cliError, isNotFoundError } from '@jahands/cli-tools'
import { z } from 'zod'

export type PublishedPackage = z.infer<typeof PublishedPackage>
export const PublishedPackage = z.object({
	name: z.string(),
	version: z.string(),
})
export const PublishedPackages = z.array(PublishedPackage)

/**
 * Reads and parses the list of published packages from the runner's temporary directory.
 * This file is generated by the changesets action in the release workflow and contains
 * information about packages that were just published.
 * @returns Array of published packages
 * @throws Error if RUNNER_TEMP is not set, file is not found, or JSON parsing fails
 */
export async function getPublishedPackages(): Promise<PublishedPackage[]> {
	const runnerTemp = await z
		.string({ error: '$RUNNER_TEMP is not set' })
		.min(1, { error: '$RUNNER_TEMP is empty' })
		.parseAsync(process.env.RUNNER_TEMP)
		.catch((e) => {
			throw cliError(z.prettifyError(e))
		})

	const publishedPackagesPath = path.join(runnerTemp, 'published-packages.json')

	echo(chalk.dim(`Reading published packages from ${publishedPackagesPath}`))

	return fs
		.readFile(publishedPackagesPath, 'utf8')
		.then((s) => PublishedPackages.parse(JSON.parse(s)))
		.catch((e) => {
			if (isNotFoundError(e)) {
				throw cliError(`No published packages file found at: ${publishedPackagesPath}`)
			} else if (e instanceof z.ZodError) {
				throw new Error(`Failed to parse published packages: ${z.prettifyError(e)}`)
			}
			throw new Error(`Failed to parse published packages: ${e}`)
		})
}

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/v4-api.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from 'zod'

type V4ErrorSchema = typeof V4ErrorSchema
const V4ErrorSchema = z.array(
	z.object({
		code: z.number().optional(),
		message: z.string(),
	})
)

export type V4Schema<TResultType extends z.ZodType> = z.ZodObject<{
	result: z.ZodNullable<TResultType>
	success: z.ZodBoolean
	errors: V4ErrorSchema
	messages: z.ZodArray<z.ZodAny>
}>

export type V4SchemaWithResultInfo<
	TResultType extends z.ZodType,
	TResultInfoType extends z.ZodType,
> = z.ZodObject<{
	result: z.ZodNullable<TResultType>
	success: z.ZodBoolean
	errors: V4ErrorSchema
	messages: z.ZodArray<z.ZodAny>
	result_info: z.ZodOptional<z.ZodNullable<TResultInfoType>>
}>

export function V4Schema<TResultType extends z.ZodType>(
	resultType: TResultType
): V4Schema<TResultType>
export function V4Schema<TResultType extends z.ZodType, TResultInfoType extends z.ZodType>(
	resultType: TResultType,
	resultInfoType: TResultInfoType
): V4SchemaWithResultInfo<TResultType, TResultInfoType>
export function V4Schema<TResultType extends z.ZodType, TResultInfoType extends z.ZodType>(
	resultType: TResultType,
	resultInfoType?: TResultInfoType
): V4Schema<TResultType> | V4SchemaWithResultInfo<TResultType, TResultInfoType> {
	if (resultInfoType) {
		return z.object({
			result: resultType.nullable(),
			result_info: resultInfoType.nullable().optional(),
			success: z.boolean(),
			errors: V4ErrorSchema,
			messages: z.array(z.any()),
		})
	} else {
		return z.object({
			result: resultType.nullable(),
			success: z.boolean(),
			errors: V4ErrorSchema,
			messages: z.array(z.any()),
		})
	}
}

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/api/workers.api.ts:
--------------------------------------------------------------------------------

```typescript
import { fetchCloudflareApi } from '../cloudflare-api'
import { WorkersService } from '../types/workers.types'
import { V4Schema } from '../v4-api'

import type { Cloudflare } from 'cloudflare'

/**
 * Fetches list of workers from Cloudflare API
 * @param client Cloudflare API Client
 * @param accountId Cloudflare account ID
 * @returns List of workers
 */
export async function handleWorkersList({
	client,
	accountId,
}: {
	client: Cloudflare
	accountId: string
}): Promise<Cloudflare.Workers.Scripts.Script[]> {
	return (await client.workers.scripts.list({ account_id: accountId })).result
}

/**
 * Get details of a worker script from Cloudflare API
 * @param client Cloudflare API Client
 * @param scriptName Name of the worker script to download
 * @param accountId Cloudflare account ID
 * @returns The script name and id
 */
export async function handleGetWorkersService({
	apiToken,
	scriptName,
	accountId,
}: {
	apiToken: string
	scriptName: string
	accountId: string
}) {
	return await fetchCloudflareApi({
		endpoint: `/workers/services/${scriptName}`,
		accountId,
		apiToken,
		responseSchema: V4Schema(WorkersService),
	})
}

/**
 * Downloads a specific worker script from Cloudflare API
 * @param client Cloudflare API Client
 * @param scriptName Name of the worker script to download
 * @param accountId Cloudflare account ID
 * @returns The worker script content
 */
export async function handleWorkerScriptDownload({
	client,
	scriptName,
	accountId,
}: {
	client: Cloudflare
	scriptName: string
	accountId: string
}): Promise<string> {
	return await client.workers.scripts.get(scriptName, { account_id: accountId })
}

```

--------------------------------------------------------------------------------
/apps/demo-day/src/demo-day.app.ts:
--------------------------------------------------------------------------------

```typescript
import { McpAgent } from 'agents/mcp'

import { getEnv } from '@repo/mcp-common/src/env'
import { CloudflareMCPServer } from '@repo/mcp-common/src/server'

// The demo day MCP server isn't stateful, so we don't have state/props
export type Props = never

export type State = never

export type Env = {
	ENVIRONMENT: 'development' | 'staging' | 'production'
	AUTORAG_NAME: 'cloudflare-docs-autorag'
	MCP_SERVER_NAME: 'PLACEHOLDER'
	MCP_SERVER_VERSION: 'PLACEHOLDER'
	MCP_OBJECT: DurableObjectNamespace<CloudflareDemoDayMCP>
	MCP_METRICS: AnalyticsEngineDataset
	ASSETS: Fetcher
}

const env = getEnv<Env>()

export class CloudflareDemoDayMCP extends McpAgent<Env, State, Props> {
	server = new CloudflareMCPServer({
		wae: env.MCP_METRICS,
		serverInfo: {
			name: env.MCP_SERVER_NAME,
			version: env.MCP_SERVER_VERSION,
		},
	})

	constructor(
		public ctx: DurableObjectState,
		public env: Env
	) {
		super(ctx, env)
	}

	async init() {
		this.server.tool(
			'mcp_demo_day_info',
			"Get information about Cloudflare's MCP Demo Day. Use this tool if the user asks about Cloudflare's MCP demo day",
			async () => {
				const res = await this.env.ASSETS.fetch('https://assets.local/index.html')
				return {
					content: [
						{
							type: 'resource',
							resource: {
								uri: 'https://demo-day.mcp.cloudflare.com',
								mimeType: 'text/html',
								text: await res.text(),
							},
						},
						{
							type: 'text',
							text: "Above is the contents of the demo day webpage, hosted at https://demo-day.mcp.cloudflare.com. Use it to answer the user's questions.",
						},
					],
				}
			}
		)
	}
}

export default CloudflareDemoDayMCP.mount('/sse')

```

--------------------------------------------------------------------------------
/apps/cloudflare-one-casb/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# cloudflare-casb-mcp-server

## 0.1.6

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]

## 0.1.5

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/api/workers-builds.api.ts:
--------------------------------------------------------------------------------

```typescript
import { fetchCloudflareApi } from '../cloudflare-api'
import {
	GetBuildLogsResult,
	GetBuildResult,
	ListBuildsByScriptResult,
	ListBuildsByScriptResultInfo,
} from '../types/workers-builds.types'
import { V4Schema } from '../v4-api'

import type { LogLine } from '../types/workers-builds.types'

export async function listBuilds({
	accountId,
	workerId,
	page = 1,
	perPage = 10,
	apiToken,
}: {
	accountId: string
	workerId: string
	page?: number
	perPage?: number
	apiToken: string
}) {
	return fetchCloudflareApi({
		endpoint: `/builds/workers/${workerId}/builds?page=${page}&per_page=${perPage}`,
		accountId,
		apiToken,
		responseSchema: V4Schema(ListBuildsByScriptResult, ListBuildsByScriptResultInfo),
	})
}

export async function getBuild({
	accountId,
	buildUUID,
	apiToken,
}: {
	accountId: string
	buildUUID: string
	apiToken: string
}) {
	return fetchCloudflareApi({
		endpoint: `/builds/builds/${buildUUID}`,
		accountId,
		apiToken,
		responseSchema: V4Schema(GetBuildResult),
	})
}

export async function getBuildLogs({
	accountId,
	buildUUID,
	apiToken,
}: {
	accountId: string
	buildUUID: string
	apiToken: string
}) {
	const allLogs: LogLine[] = []
	let cursor: string | undefined = undefined
	let hasMore = true

	while (hasMore) {
		let endpoint = `/builds/builds/${buildUUID}/logs`
		if (cursor) {
			endpoint += `?cursor=${cursor}`
		}

		const res = await fetchCloudflareApi({
			endpoint,
			accountId,
			apiToken,
			responseSchema: V4Schema(GetBuildLogsResult),
		})

		if (res.result) {
			allLogs.push(...res.result.lines)

			if (res.result.cursor && res.result.truncated) {
				cursor = res.result.cursor
			} else {
				hasMore = false
			}
		}
	}

	return allLogs
}

```

--------------------------------------------------------------------------------
/packages/mcp-observability/src/metrics.ts:
--------------------------------------------------------------------------------

```typescript
import { type ClientCapabilities } from '@modelcontextprotocol/sdk/types.js'

import { MetricsEvent, MetricsEventIndexIds } from './analytics-engine'

/**
 * TODO: once there are better hooks into MCP servers, we should track the session ID
 */
export class ToolCall extends MetricsEvent {
	constructor(
		private toolCall: {
			userId?: string
			toolName: string
			errorCode?: number
		}
	) {
		super()
	}

	toDataPoint(): AnalyticsEngineDataPoint {
		return {
			indexes: [MetricsEventIndexIds.TOOL_CALL],
			blobs: this.mapBlobs({
				blob3: this.toolCall.userId,
				blob4: this.toolCall.toolName,
			}),
			doubles: this.mapDoubles({
				double1: this.toolCall.errorCode,
			}),
		}
	}
}

export class SessionStart extends MetricsEvent {
	constructor(
		private session: {
			userId?: string
			clientInfo?: {
				name: string
				version: string
			}
			clientCapabilities?: ClientCapabilities
		}
	) {
		super()
	}

	toDataPoint(): AnalyticsEngineDataPoint {
		return {
			indexes: [MetricsEventIndexIds.SESSION_START],
			blobs: this.mapBlobs({
				blob3: this.session.userId,
				blob4: this.session.clientInfo?.name,
				blob5: this.session.clientInfo?.version,
			}),
			doubles: this.mapDoubles({
				double1: this.session.clientCapabilities?.roots ? 1 : 0,
				double2: this.session.clientCapabilities?.sampling ? 1 : 0,
			}),
		}
	}
}

export class AuthUser extends MetricsEvent {
	constructor(
		private authUser: {
			userId?: string
			errorMessage?: string
		}
	) {
		super()
	}

	toDataPoint(): AnalyticsEngineDataPoint {
		return {
			indexes: [MetricsEventIndexIds.AUTH_USER],
			blobs: this.mapBlobs({
				blob3: this.authUser.userId,
				blob4: this.authUser.errorMessage,
			}),
		}
	}
}

```

--------------------------------------------------------------------------------
/apps/workers-bindings/evals/hyperdrive.eval.ts:
--------------------------------------------------------------------------------

```typescript
import { expect } from 'vitest'
import { describeEval } from 'vitest-evals'

import { runTask } from '@repo/eval-tools/src/runTask'
import { checkFactuality } from '@repo/eval-tools/src/scorers'
import { eachModel } from '@repo/eval-tools/src/test-models'
import { HYPERDRIVE_TOOLS } from '@repo/mcp-common/src/tools/hyperdrive.tools'

import { initializeClient } from './utils' // Assuming utils.ts will exist here

// TODO: Add test for creating hyperdrive config with the following params once we can securely pass parameters to the tool. See: https://github.com/modelcontextprotocol/modelcontextprotocol/pull/382
// const HYPERDRIVE_NAME = 'neon-test-hyperdrive'
// const HYPERDRIVE_DATABASE = 'neondb'
// const HYPERDRIVE_HOST = 'ep-late-cell-a4fm3g5p-pooler.us-east-1.aws.neon.tech'
// const HYPERDRIVE_PORT = 5432
// const HYPERDRIVE_USER = 'neondb_owner'
// const HYPERDRIVE_PASSWORD = 'my-test-password'

eachModel('$modelName', ({ model }) => {
	describeEval('Hyperdrive Tool Evaluations', {
		data: async () => [
			{
				input: `List my hyperdrive configurations.`,
				expected: `The ${HYPERDRIVE_TOOLS.hyperdrive_configs_list} tool should be called to list my hyperdrive configurations.`,
			},
		],
		task: async (input: string) => {
			const client = await initializeClient(/* Pass necessary mocks/config */)
			const { promptOutput, toolCalls } = await runTask(client, model, input)

			const toolCall = toolCalls.find(
				(call) => call.toolName === HYPERDRIVE_TOOLS.hyperdrive_configs_list
			)
			expect(
				toolCall,
				`Tool ${HYPERDRIVE_TOOLS.hyperdrive_configs_list} was not called`
			).toBeDefined()

			return promptOutput
		},
		scorers: [checkFactuality],
		threshold: 1,
		timeout: 60000,
	})
})

```

--------------------------------------------------------------------------------
/packages/eslint-config/default.cjs:
--------------------------------------------------------------------------------

```
const { resolve } = require('node:path')

const project = resolve(process.cwd(), 'tsconfig.json')

/** @type {import("eslint").Linter.Config} */
module.exports = {
	ignorePatterns: ['.*.{js,cjs}', '**/node_modules/**', '**/dist/**', '**/dist2/**'],
	plugins: ['@typescript-eslint', 'import', 'unused-imports'],
	extends: ['turbo'],
	settings: {
		'import/resolver': {
			typescript: {
				project,
			},
		},
	},
	overrides: [
		// TypeScript
		{
			// enable the rule specifically for TypeScript files
			files: ['**/*.{ts,tsx,mjs}'],
			parser: '@typescript-eslint/parser',
			parserOptions: {
				ecmaVersion: 2024,
				sourceType: 'module',
				project: true,
			},
			extends: [
				'eslint:recommended',
				'plugin:@typescript-eslint/recommended',
				'plugin:import/typescript',
				'turbo',
				'prettier', // disable rules that conflict with prettier
			],
			rules: {
				'@typescript-eslint/consistent-type-imports': ['warn', { prefer: 'type-imports' }],
				'@typescript-eslint/explicit-function-return-type': 'off',
				'react-hooks/rules-of-hooks': 'off',
				'@typescript-eslint/ban-ts-comment': 'off',
				'@typescript-eslint/no-floating-promises': 'warn',
				'unused-imports/no-unused-imports': 'warn',
				'@typescript-eslint/array-type': ['warn', { default: 'array-simple' }],
				'@typescript-eslint/no-unused-vars': [
					'warn',
					{
						argsIgnorePattern: '^_',
						varsIgnorePattern: '^_',
						caughtErrorsIgnorePattern: '^_',
					},
				],
				'@typescript-eslint/no-explicit-any': 'off',
				'prefer-const': 'warn',
				'no-mixed-spaces-and-tabs': ['error', 'smart-tabs'],
				'no-empty': 'warn',
			},
		},

		// Node
		{
			files: ['.eslintrc.cjs'],
			env: {
				node: true,
			},
		},
	],
}

```

--------------------------------------------------------------------------------
/apps/radar/src/radar.context.ts:
--------------------------------------------------------------------------------

```typescript
import type { RadarMCP, UserDetails } from './radar.app'

export interface Env {
	OAUTH_KV: KVNamespace
	ENVIRONMENT: 'development' | 'staging' | 'production'
	MCP_SERVER_NAME: string
	MCP_SERVER_VERSION: string
	CLOUDFLARE_CLIENT_ID: string
	CLOUDFLARE_CLIENT_SECRET: string
	MCP_OBJECT: DurableObjectNamespace<RadarMCP>
	USER_DETAILS: DurableObjectNamespace<UserDetails>
	MCP_METRICS: AnalyticsEngineDataset
	DEV_DISABLE_OAUTH: string
	DEV_CLOUDFLARE_API_TOKEN: string
	DEV_CLOUDFLARE_EMAIL: string
}

export const BASE_INSTRUCTIONS = /* markdown */ `
# Cloudflare Radar MCP Server

This server integrates tools powered by the Cloudflare Radar API to provide insights into global Internet traffic,
trends, and other related utilities.

An active account is **only required** for URL Scanner-related tools (e.g., \`scan_url\`).

For tools related to Internet trends and insights, analyze the results and, when appropriate, generate visualizations
such as line charts, pie charts, bar charts, stacked area charts, choropleth maps, treemaps, or other relevant chart types.

### Making comparisons

Many tools support **array-based filters** to enable comparisons across multiple criteria.
In such cases, the array index corresponds to a distinct data series.
For each data series, provide a corresponding \`dateRange\`, or alternatively a \`dateStart\` and \`dateEnd\` pair.
Example: To compare HTTP traffic between Portugal and Spain over the last 7 days:
- \`dateRange: ["7d", "7d"]\`
- \`location: ["PT", "ES"]\`

This applies to date filters and other filters that support comparison across multiple values.
If a tool does **not** support array-based filters, you can achieve the same comparison by making multiple separate
calls to the tool.
`

```

--------------------------------------------------------------------------------
/apps/demo-day/frontend/public/atlassian.svg:
--------------------------------------------------------------------------------

```
<svg width="360" height="360" viewBox="0 0 360 360" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M105.984 167.061L106.015 167.101L106.049 167.138C129.194 191.788 144.778 224.83 151.273 258.534C157.769 292.244 155.156 326.525 142.022 353.67L142.016 353.682C141.265 355.289 140.062 356.642 138.554 357.575C137.046 358.508 135.299 358.981 133.527 358.935L133.515 358.935H133.502H10.7182H10.7151C9.23699 358.94 7.77879 358.594 6.4598 357.927L6.45595 357.925C4.19542 356.793 2.47638 354.809 1.67691 352.409C0.877449 350.009 1.06301 347.39 2.19275 345.127C2.19278 345.127 2.19281 345.127 2.19285 345.127L90.3202 168.711L90.3237 168.704L90.327 168.697C90.9615 167.377 91.8885 166.218 93.0374 165.31C94.9874 163.831 97.4428 163.185 99.8675 163.512C102.295 163.839 104.495 165.115 105.984 167.061Z" stroke="white" stroke-width="1"/>
<path d="M172.393 6.45857L172.555 6.21014V6.09531C173.28 4.65453 174.384 3.43639 175.748 2.5722C177.175 1.66894 178.828 1.18945 180.516 1.18945C182.204 1.18945 183.857 1.66894 185.284 2.5722C186.71 3.47547 187.851 4.76544 188.574 6.29215L188.578 6.30179L188.583 6.31132L357.893 345.12C357.894 345.122 357.895 345.123 357.895 345.124C358.546 346.453 358.883 347.913 358.882 349.393V349.396C358.885 350.649 358.64 351.891 358.162 353.05C357.684 354.209 356.982 355.262 356.096 356.148C355.21 357.035 354.158 357.737 353 358.215C351.842 358.694 350.601 358.938 349.349 358.935H349.346H226.588C224.818 358.935 223.082 358.441 221.577 357.509C220.071 356.577 218.854 355.244 218.062 353.659L217.168 354.106L218.062 353.659L158.867 235.194C158.866 235.193 158.866 235.192 158.865 235.191C141.114 199.162 133.027 159.135 135.399 119.036C137.77 78.936 150.518 40.1415 172.393 6.45857Z" stroke="white" stroke-width="1"/>
</svg>

```

--------------------------------------------------------------------------------
/apps/demo-day/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# demo-day

## 0.1.6

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.5

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/docs-autorag/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# docs-autorag

## 0.1.6

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.5

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/demo-day/frontend/public/canva.svg:
--------------------------------------------------------------------------------

```
<svg width="304" height="420" viewBox="0 0 304 420" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M290.187 321.595L290.135 321.647L290.09 321.707C272.996 344.813 250.906 368.88 221.814 386.92L221.807 386.924L221.8 386.928C193.664 404.999 161.592 419 123.543 419C88.5958 419 59.5943 401.035 43.5799 386.037C19.595 363.071 6.56214 330.071 2.55014 299.011C-3.46858 250.902 8.31751 194.948 33.0794 144.089C57.8401 93.2326 95.5276 47.57 141.198 19.9928L141.207 19.9872C162.216 6.99381 185.221 1 207.219 1C251.089 1 283.907 31.8603 287.883 69.6012L287.885 69.6134C289.882 86.5751 287.629 102.223 280.185 115.981C272.741 129.739 260.059 141.695 241.048 151.192L241.039 151.196L241.03 151.201C231.515 156.204 224.336 158.41 219.222 158.897C214.092 159.385 211.264 158.136 210.051 156.544C208.424 154.07 209.148 149.624 212.859 146.843L212.878 146.829L212.897 146.813C230.644 132.122 239.862 118.62 244.092 104.404C248.313 90.2184 247.531 75.4369 245.513 58.3003L245.512 58.2912L245.511 58.282C242.443 35.8101 228.045 21.1583 211.251 21.1583C193.508 21.1583 173.937 31.0955 154.851 47.5566C135.741 64.0391 116.994 87.1669 100.886 113.799C68.6873 167.035 46.9037 234.492 53.9966 291.198C56.5334 313.493 64.6501 337.6 79.2817 356.159C93.9361 374.746 115.13 387.763 143.706 387.763C162.02 387.763 182.34 382.685 199.616 373.549C219.299 363.464 233.485 354.864 245.664 344.725C257.846 334.583 267.982 322.931 279.602 306.78C281.129 304.745 282.652 302.462 284.156 300.208L284.165 300.195C285.681 297.924 287.177 295.682 288.669 293.694L288.724 293.622L288.764 293.541C290.534 290.004 294.089 289.058 296.943 289.058C299.416 289.058 303 291.632 303 296.115C303 298.979 302.031 304.78 298.179 309.591L298.112 309.674L298.065 309.768C297.048 311.8 294.088 317.697 290.187 321.595Z" stroke="white" stroke-width="1"/>
</svg>

```

--------------------------------------------------------------------------------
/apps/radar/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# cloudflare-radar-mcp-server

## 0.1.6

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.5

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/autorag/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# cloudflare-autorag-mcp-server

## 0.1.6

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.5

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/browser-rendering/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# cloudflare-browser-mcp-server

## 0.1.6

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.5

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/ai-gateway/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# cloudflare-ai-gateway-mcp-server

## 0.1.6

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.5

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/sandbox-container/server/containerManager.ts:
--------------------------------------------------------------------------------

```typescript
import { DurableObject } from 'cloudflare:workers'

import { getEnv } from '@repo/mcp-common/src/env'
import { MetricsTracker } from '@repo/mcp-observability'

import { ContainerEvent } from './metrics'

import type { Env } from './sandbox.server.context'

const env = getEnv<Env>()
export class ContainerManager extends DurableObject<Env> {
	metrics = new MetricsTracker(env.MCP_METRICS, {
		name: env.MCP_SERVER_NAME,
		version: env.MCP_SERVER_VERSION,
	})

	constructor(
		public ctx: DurableObjectState,
		public env: Env
	) {
		super(ctx, env)
	}

	async trackContainer(id: string) {
		await this.ctx.storage.put(id, new Date())
	}

	async killContainer(id: string) {
		await this.ctx.storage.delete(id)
	}

	async tryKillOldContainers() {
		const activeContainers = await this.ctx.storage.list<Date>()
		for (const c of activeContainers) {
			const id = c[0]
			const now = new Date()
			const time = c[1]

			console.log(id, time, now, now.valueOf() - time.valueOf())

			// 15m timeout for container lifetime
			if (now.valueOf() - time.valueOf() > 15 * 60 * 1000) {
				await this.killContainer(id)
				// TODO: Figure out why we were running in to invalid durable object id the id does not match this durable object class error
				const doId = this.env.USER_CONTAINER.idFromString(id)
				const stub = this.env.USER_CONTAINER.get(doId)
				await stub.destroyContainer()
			}
		}
	}

	async listActive(): Promise<string[]> {
		const activeContainers = await this.ctx.storage.list()
		const activeIds: string[] = []
		for (const c of activeContainers.keys()) {
			activeIds.push(c)
		}

		this.metrics.logEvent(
			new ContainerEvent({
				active: activeIds.length,
			})
		)

		return activeIds
	}
}

export function getContainerManager(env: Env): DurableObjectStub<ContainerManager> {
	const id = env.CONTAINER_MANAGER.idFromName('manager')
	return env.CONTAINER_MANAGER.get(id)
}

```

--------------------------------------------------------------------------------
/packages/tools/src/tsconfig.ts:
--------------------------------------------------------------------------------

```typescript
import { inspect } from 'node:util'

import type {
	convertCompilerOptionsFromJson,
	createProgram,
	readConfigFile,
	sys,
	CompilerOptions as TSCompilerOptions,
} from 'typescript'

export type { TSCompilerOptions }

interface TSModule {
	readConfigFile: typeof readConfigFile
	convertCompilerOptionsFromJson: typeof convertCompilerOptionsFromJson
	sys: typeof sys
	createProgram: typeof createProgram
}

/**
 * TypeScript helpers. This is a class so that we can dynamically import the TypeScript module
 * to reduce runx start time for commands that don't use the typescript package.
 *
 * @example
 *
 * ```ts
 * const tsHelpers = await new TSHelpers().init()
 * const { ts } = tsHelpers
 * const tsConfig = tsHelpers.getTSConfig()
 * ts.createProgram(entryPoints, tsConfig).emit()
 * ```
 */
export class TSHelpers {
	#ts: TSModule | undefined
	public get ts(): TSModule {
		if (!this.#ts) {
			throw new Error('TSHelpers not initialized. Call init() first.')
		}
		return this.#ts
	}

	async init(): Promise<TSHelpers> {
		this.#ts = (await import('typescript')) as TSModule
		return this
	}

	getTSConfig(configPath = 'tsconfig.json'): TSCompilerOptions {
		const jsonCompopts = this.getCompilerOptionsJSONFollowExtends(configPath)
		const tmp = this.ts.convertCompilerOptionsFromJson(jsonCompopts, '')
		if (tmp.errors.length > 0) {
			throw new Error(`failed parse config: ${inspect(tmp)}`)
		}
		const tsCompopts: TSCompilerOptions = tmp.options
		return tsCompopts
	}

	getCompilerOptionsJSONFollowExtends(configPath: string): {
		[key: string]: unknown
	} {
		let compopts = {}
		const config = this.ts.readConfigFile(configPath, this.ts.sys.readFile).config
		if (config.extends !== undefined) {
			const rqrpath = require.resolve(config.extends)
			compopts = this.getCompilerOptionsJSONFollowExtends(rqrpath)
		}
		return {
			...compopts,
			...config.compilerOptions,
		}
	}
}

```

--------------------------------------------------------------------------------
/apps/workers-bindings/evals/accounts.eval.ts:
--------------------------------------------------------------------------------

```typescript
import { expect } from 'vitest'
import { describeEval } from 'vitest-evals'

import { runTask } from '@repo/eval-tools/src/runTask'
import { checkFactuality } from '@repo/eval-tools/src/scorers'
import { eachModel } from '@repo/eval-tools/src/test-models'

import { initializeClient } from './utils' // Assuming utils.ts will exist here

// Define a mock account ID for testing
const MOCK_ACCOUNT_ID = 'mock-account-12345'

eachModel('$modelName', ({ model }) => {
	describeEval('List Cloudflare Accounts', {
		data: async () => [
			{
				input: 'List all my Cloudflare accounts.',
				expected: 'The accounts_list tool should be called to retrieve the list of accounts.',
			},
		],
		task: async (input: string) => {
			const client = await initializeClient()
			const { promptOutput, toolCalls } = await runTask(client, model, input)

			const toolCall = toolCalls.find((call) => call.toolName === 'accounts_list')
			expect(toolCall, 'Tool accounts_list was not called').toBeDefined()
			return promptOutput
		},
		scorers: [checkFactuality],
		threshold: 1,
		timeout: 60000, // 60 seconds
	})
	describeEval('Set Active Cloudflare Account', {
		data: async () => [
			{
				input: `Set my active Cloudflare account to ${MOCK_ACCOUNT_ID}.`,
				expected: `The set_active_account tool should be called with the account ID ${MOCK_ACCOUNT_ID}.`,
			},
		],
		task: async (input: string) => {
			const client = await initializeClient()
			const { promptOutput, toolCalls } = await runTask(client, model, input)
			const toolCall = toolCalls.find((call) => call.toolName === 'set_active_account')
			expect(toolCall, 'Tool set_active_account was not called').toBeDefined()

			expect(toolCall?.args, 'Arguments for set_active_account did not match').toEqual(
				expect.objectContaining({ activeAccountIdParam: MOCK_ACCOUNT_ID })
			)
			return promptOutput
		},
		scorers: [checkFactuality],
		threshold: 1,
		timeout: 60000, // 60 seconds
	})
})

```

--------------------------------------------------------------------------------
/apps/logpush/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# logpush

## 0.1.7

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.6

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.1.5

### Patch Changes

- dffbd36: Use proper wrangler deploy in all servers so we get the name and version

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/auditlogs/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# auditlogs

## 0.1.7

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.6

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.1.5

### Patch Changes

- dffbd36: Use proper wrangler deploy in all servers so we get the name and version

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/dns-analytics/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# dns-analytics

## 0.1.7

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.6

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.1.5

### Patch Changes

- dffbd36: Use proper wrangler deploy in all servers so we get the name and version

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/workers-builds/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# workers-builds

## 0.1.7

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.6

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.1.5

### Patch Changes

- dffbd36: Use proper wrangler deploy in all servers so we get the name and version

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/demo-day/frontend/public/sentry.svg:
--------------------------------------------------------------------------------

```
<svg width="492" height="442" viewBox="0 0 492 442" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M484.774 415.775C493.975 399.801 492.903 379.593 481.831 360.377L292.421 31.2701C281.349 12.0383 264.446 1 246.059 1C227.654 1 210.74 12.0383 199.683 31.2701L141.245 132.747C155.754 140.9 169.621 150.146 182.725 160.404C252.509 215.006 299.53 297.485 307.013 391.018H270.318C263.099 311.013 223.255 240.341 164.253 192.49C151.325 181.997 137.516 172.636 122.98 164.514L54.5168 283.409C69.398 291.394 82.7652 301.83 94.2089 314.159C113.628 335.151 127.189 361.655 132.332 391.031L71.021 391.003C69.4149 391.002 67.8246 390.686 66.3411 390.07C64.8576 389.455 63.51 388.554 62.3755 387.417C61.2409 386.281 60.3417 384.932 59.7292 383.448C59.1167 381.964 58.803 380.374 58.806 378.769C58.8124 376.73 59.3184 374.724 60.2798 372.926L75.7505 346.587C64.3269 334.228 50.9285 323.85 36.1023 315.879L10.1487 360.335C-0.923664 379.566 -1.9955 399.759 7.20502 415.733C16.3921 431.72 34.3683 440.889 56.5245 440.889H182.932C183.825 433.164 184.348 425.302 184.348 417.355C184.348 408.434 183.716 399.663 182.587 391.045C176.357 343.303 153.443 300.77 119.872 269.54L139.017 236.299C183.454 274.831 213.63 329.433 220.367 391.045C221.33 399.692 221.852 408.461 221.852 417.355C221.852 425.302 221.426 433.135 220.683 440.889H357.047C357.529 433.095 357.858 425.259 357.858 417.355C357.858 408.49 357.447 399.745 356.842 391.045C349.071 279.093 292.283 180.489 207.811 116.842L235.606 68.5515C236.691 66.7488 238.223 65.2571 240.054 64.2213C241.886 63.1855 243.954 62.6408 246.059 62.6402C248.218 62.6387 250.338 63.2122 252.202 64.3016C254.065 65.391 255.605 66.9569 256.662 68.8384L431.715 372.955C432.679 374.751 433.184 376.757 433.185 378.795C433.185 385.56 427.726 391.045 420.974 391.045L393.508 391.071C394.113 399.787 394.524 408.53 394.524 417.383C394.524 425.288 394.195 433.135 393.699 440.918H435.455C457.611 440.918 475.587 431.762 484.774 415.775Z" stroke="white" stroke-width="1"/>
</svg>

```

--------------------------------------------------------------------------------
/apps/sandbox-container/package.json:
--------------------------------------------------------------------------------

```json
{
	"name": "containers-mcp",
	"version": "0.2.6",
	"private": true,
	"type": "module",
	"scripts": {
		"check:types": "run-tsc",
		"check:lint": "run-eslint-workers",
		"deploy": "run-wrangler-deploy",
		"dev": "concurrently \"tsx container/sandbox.container.app.ts\" \"wrangler dev --var \"ENVIRONMENT:dev\"\"",
		"build:container": "docker build --platform linux/amd64 --tag sandbox-container:$(git rev-parse --short HEAD) -f Dockerfile ../../ && wrangler containers push sandbox-container:$(git rev-parse --short HEAD)",
		"start": "wrangler dev",
		"start:container": "tsx container/sandbox.container.app.ts",
		"postinstall": "mkdir -p workdir",
		"test": "vitest",
		"types": "wrangler types --include-env=false",
		"eval:dev": "start-server-and-test --expect 404 eval:server http://localhost:8976 'vitest --testTimeout=60000 --config vitest.config.evals.ts'",
		"eval:server": "concurrently \"tsx container/sandbox.container.app.ts\" \"wrangler dev --var ENVIRONMENT:test --var DEV_DISABLE_OAUTH:true --var DEV_CLOUDFLARE_EMAIL:[email protected]\"",
		"eval:ci": "start-server-and-test --expect 404 eval:server http://localhost:8976 'vitest run --testTimeout=60000 --config vitest.config.evals.ts'"
	},
	"dependencies": {
		"@cloudflare/workers-oauth-provider": "0.0.5",
		"@hono/node-server": "1.13.8",
		"@hono/zod-validator": "0.4.3",
		"@modelcontextprotocol/sdk": "1.18.2",
		"@n8n/json-schema-to-zod": "1.1.0",
		"@repo/eval-tools": "workspace:*",
		"@repo/mcp-common": "workspace:*",
		"@repo/mcp-observability": "workspace:*",
		"agents": "0.2.7",
		"cron-schedule": "5.0.4",
		"esbuild": "0.25.1",
		"hono": "4.7.6",
		"mime": "4.0.6",
		"simple-git-hooks": "2.12.1",
		"tsx": "4.19.3",
		"vitest-evals": "0.1.4",
		"zod": "3.24.2"
	},
	"devDependencies": {
		"@cloudflare/vitest-pool-workers": "0.8.14",
		"@types/mock-fs": "4.13.4",
		"@types/node": "22.14.1",
		"ai": "4.3.10",
		"concurrently": "9.1.2",
		"mock-fs": "5.5.0",
		"start-server-and-test": "2.0.11",
		"wrangler": "4.10.0"
	}
}

```

--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------

```yaml
name: Release

on:
  push:
    branches: ['main']

env:
  FORCE_COLOR: 1

jobs:
  create-release-pr:
    name: Create Release PR
    runs-on: ubuntu-24.04
    permissions:
      contents: write
      pull-requests: write
    timeout-minutes: 5
    concurrency: ${{ github.workflow }}-create-release-pr
    outputs:
      published: ${{ steps.create-release-pr.outputs.published }}
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v4
      - uses: ./.github/actions/setup
      - name: Create Release PR
        id: create-release-pr
        uses: changesets/action@v1
        with:
          publish: pnpm changeset publish
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Save Published Packages
        if: steps.create-release-pr.outputs.published == 'true'
        run: |
          echo '${{steps.create-release-pr.outputs.publishedPackages}}' \
            > ${{ github.workspace }}/published-packages.json
      - name: Upload Published Packages
        if: steps.create-release-pr.outputs.published == 'true'
        uses: actions/upload-artifact@v4
        with:
          name: published-packages
          path: ${{ github.workspace }}/published-packages.json

  deploy-production:
    name: Deploy (production)
    needs: create-release-pr
    if: needs.create-release-pr.outputs.published == 'true'
    runs-on: ubuntu-24.04
    timeout-minutes: 10
    concurrency: ${{ github.workflow }}-deploy-production
    permissions:
      contents: read
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v4
      - name: Download published packages
        uses: actions/download-artifact@v4
        with:
          name: published-packages
          path: ${{ runner.temp }}
      - uses: ./.github/actions/setup
      - name: Deploy Published Workers (production)
        run: pnpm runx deploy-published-workers --env production
        env:
          CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}

```

--------------------------------------------------------------------------------
/apps/sandbox-container/server/sandbox.server.app.ts:
--------------------------------------------------------------------------------

```typescript
import OAuthProvider from '@cloudflare/workers-oauth-provider'

import { createApiHandler } from '@repo/mcp-common/src/api-handler'
import { handleApiTokenMode, isApiTokenRequest } from '@repo/mcp-common/src/api-token-mode'
import {
	createAuthHandlers,
	handleTokenExchangeCallback,
} from '@repo/mcp-common/src/cloudflare-oauth-handler'
import { getEnv } from '@repo/mcp-common/src/env'
import { RequiredScopes } from '@repo/mcp-common/src/scopes'
import { MetricsTracker } from '@repo/mcp-observability'

import { ContainerManager } from './containerManager'
import { ContainerMcpAgent } from './containerMcp'
import { UserContainer } from './userContainer'

import type { AuthProps } from '@repo/mcp-common/src/cloudflare-oauth-handler'
import type { Env } from './sandbox.server.context'

export { ContainerManager, ContainerMcpAgent, UserContainer }

const env = getEnv<Env>()

const metrics = new MetricsTracker(env.MCP_METRICS, {
	name: env.MCP_SERVER_NAME,
	version: env.MCP_SERVER_VERSION,
})

// Context from the auth process, encrypted & stored in the auth token
// and provided to the DurableMCP as this.props
export type Props = AuthProps

const ContainerScopes = {
	...RequiredScopes,
	'account:read': 'See your account info such as account details, analytics, and memberships.',
} as const

export default {
	fetch: async (req: Request, env: Env, ctx: ExecutionContext) => {
		if (await isApiTokenRequest(req, env)) {
			return await handleApiTokenMode(ContainerMcpAgent, req, env, ctx)
		}

		return new OAuthProvider({
			apiRoute: ['/mcp', '/sse'],
			apiHandler: createApiHandler(ContainerMcpAgent),
			// @ts-ignore
			defaultHandler: createAuthHandlers({ scopes: ContainerScopes, metrics }),
			authorizeEndpoint: '/oauth/authorize',
			tokenEndpoint: '/token',
			tokenExchangeCallback: (options) =>
				handleTokenExchangeCallback(
					options,
					env.CLOUDFLARE_CLIENT_ID,
					env.CLOUDFLARE_CLIENT_SECRET
				),
			// Cloudflare access token TTL
			accessTokenTTL: 3600,
			clientRegistrationEndpoint: '/register',
		}).fetch(req, env, ctx)
	},
}

```

--------------------------------------------------------------------------------
/apps/docs-vectorize/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# docs-vectorize

## 0.4.1

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.4.0

### Minor Changes

- dee0a7b: Updated the model for docs search to embeddinggemma-300m

## 0.3.3

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.3.2

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.3.1

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.3.0

### Minor Changes

- f885d07: Add search docs tool to bindings and obs servers

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.2.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.2.0

### Minor Changes

- 89bfaf4: feat: add Pages to Workers migration guide to docs-vectorize MCP server

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/cloudflare-api.ts:
--------------------------------------------------------------------------------

```typescript
import { Cloudflare } from 'cloudflare'
import { env } from 'cloudflare:workers'

import type { z } from 'zod'

export function getCloudflareClient(apiToken: string) {
	// @ts-expect-error We don't have actual env in this package
	if (env.DEV_DISABLE_OAUTH) {
		return new Cloudflare({
			// @ts-expect-error We don't have actual env in this package, but we know this is defined because the initial Oauth handshake will fail without it
			apiEmail: env.DEV_CLOUDFLARE_EMAIL,
			// @ts-expect-error We don't have actual env in this package, but we know this is defined because the initial Oauth handshake will fail without it
			apiKey: env.DEV_CLOUDFLARE_API_TOKEN,
		})
	}

	return new Cloudflare({ apiToken })
}

/**
 * Makes a request to the Cloudflare API
 * @param endpoint API endpoint path (without the base URL)
 * @param accountId Cloudflare account ID
 * @param apiToken Cloudflare API token
 * @param options Additional fetch options
 * @returns The API response
 */
export async function fetchCloudflareApi<T>({
	endpoint,
	accountId,
	apiToken,
	responseSchema,
	options = {},
}: {
	endpoint: string
	accountId: string
	apiToken: string
	responseSchema?: z.ZodType<T>
	options?: RequestInit
}): Promise<T> {
	const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}${endpoint}`

	// @ts-expect-error We don't have actual env in this package
	if (env.DEV_DISABLE_OAUTH) {
		options.headers = {
			...options.headers,
			// @ts-expect-error We don't have actual env in this package
			'X-Auth-Email': env.DEV_CLOUDFLARE_EMAIL,
			// @ts-expect-error We don't have actual env in this package
			'X-Auth-Key': env.DEV_CLOUDFLARE_API_TOKEN,
		}
	}
	const response = await fetch(url, {
		...options,
		headers: {
			Authorization: `Bearer ${apiToken}`,
			...(options.headers || {}),
		},
	})

	if (!response.ok) {
		const error = await response.text()
		throw new Error(`Cloudflare API request failed: ${error}`)
	}

	const data = await response.json()

	// If a schema is provided, validate the response
	if (responseSchema) {
		return responseSchema.parse(data)
	}

	return data as T
}

```

--------------------------------------------------------------------------------
/apps/sandbox-container/server/containerHelpers.ts:
--------------------------------------------------------------------------------

```typescript
export const MAX_CONTAINERS = 50
export async function startAndWaitForPort(
	environment: 'dev' | 'prod' | 'test',
	container: Container | undefined,
	portToAwait: number,
	maxTries = 10
): Promise<boolean> {
	if (environment === 'dev' || environment === 'test') {
		console.log('Running in dev, assuming locally running container')
		return true
	}

	if (!container) {
		throw new Error('Error: ctx.container is undefined. Does this DO support containers?')
	}

	const port = container.getTcpPort(portToAwait)
	// promise to make sure the container does not exit
	let monitor

	for (let i = 0; i < maxTries; i++) {
		try {
			if (!container.running) {
				console.log('starting container')
				container.start({
					enableInternet: true,
				})

				// force DO to keep track of running state
				monitor = container.monitor()
				void monitor.then(() => console.log('Container exited'))
			}

			const conn = await port.connect(`10.0.0.1:${portToAwait}`)
			await conn.close()
			console.log('Connected')
			return true
		} catch (err: any) {
			if (!(err instanceof Error)) {
				throw err
			}

			console.error('Error connecting to the container on', i, 'try', err)

			if (err.message.includes('listening')) {
				await new Promise((res) => setTimeout(res, 300))
				continue
			}

			// no container yet
			if (err.message.includes('there is no container instance that can be provided')) {
				await new Promise((res) => setTimeout(res, 300))
				continue
			}

			console.log(err)
			return false
		}
	}

	return false
}

export async function proxyFetch(
	environment: 'dev' | 'prod' | 'test',
	container: Container | undefined,
	request: Request,
	portNumber: number
): Promise<Response> {
	if (environment === 'dev' || environment === 'test') {
		const url = request.url
			.replace('https://', 'http://')
			.replace('http://host', 'http://localhost')
		return fetch(url, request.clone() as Request)
	}

	if (!container) {
		throw new Error('Error: ctx.container is undefined. Does this DO support containers?')
	}

	return await container
		.getTcpPort(portNumber)
		.fetch(request.url.replace('https://', 'http://'), request.clone() as Request)
}

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/api-token-mode.ts:
--------------------------------------------------------------------------------

```typescript
import { getUserAndAccounts } from './cloudflare-oauth-handler'

import type { McpAgent } from 'agents/mcp'
import type { AuthProps } from './cloudflare-oauth-handler'

interface RequiredEnv {
	DEV_CLOUDFLARE_API_TOKEN: string
	DEV_CLOUDFLARE_EMAIL: string
	DEV_DISABLE_OAUTH: string
}

export async function isApiTokenRequest(req: Request, env: RequiredEnv) {
	// shortcircuit for dev
	if (env.DEV_CLOUDFLARE_API_TOKEN && env.DEV_DISABLE_OAUTH === 'true') {
		return true
	}

	const authHeader = req.headers.get('Authorization')
	if (!authHeader) return false

	const [type, token] = authHeader.split(' ')
	if (type !== 'Bearer') return false

	// Return true only if the token was issued by the OAuthProvider.
	// A token provisioned by the OAuthProvider has 3 parts, split by colons.
	const codeParts = token.split(':')
	return codeParts.length !== 3
}

export async function handleApiTokenMode<
	T extends typeof McpAgent<unknown, unknown, Record<string, unknown>>,
>(agent: T, req: Request, env: RequiredEnv, ctx: ExecutionContext) {
	// Handle global API token case
	let opts, token
	// dev mode
	if (
		env.DEV_CLOUDFLARE_API_TOKEN &&
		env.DEV_CLOUDFLARE_EMAIL &&
		env.DEV_DISABLE_OAUTH === 'true'
	) {
		opts = {
			'X-Auth-Key': env.DEV_CLOUDFLARE_API_TOKEN,
			'X-Auth-Email': env.DEV_CLOUDFLARE_EMAIL,
		}
		token = env.DEV_CLOUDFLARE_API_TOKEN
		// header mode
	} else {
		const authHeader = req.headers.get('Authorization')
		if (!authHeader) {
			throw new Error('Authorization header is required')
		}

		const [type, tokenStr] = authHeader.split(' ')
		if (type !== 'Bearer') {
			throw new Error('Invalid authorization type, must be Bearer')
		}
		token = tokenStr
	}

	const { user, accounts } = await getUserAndAccounts(token, opts)

	// If user is null, handle API token mode
	if (user === null) {
		ctx.props = {
			type: 'account_token',
			accessToken: token,
			// we always select the first account from the response,
			// this assumes that account owned tokens can only access one account
			account: accounts[0],
		} satisfies AuthProps
	} else {
		ctx.props = {
			type: 'user_token',
			accessToken: token,
			user,
			accounts,
		} satisfies AuthProps
	}
	return agent.mount('/sse').fetch(req, env, ctx)
}

```

--------------------------------------------------------------------------------
/apps/dex-analysis/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# dex-analysis

## 0.2.2

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.2.1

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.2.0

### Minor Changes

- 9496e21: Add tool for analyzing WARP-diags for common issues via bonobo

## 0.1.7

### Patch Changes

- dffbd36: Improve DEX remote captures tools, separate by type for clarity

## 0.1.6

### Patch Changes

- d672471: dex-analysis: add WARP diag analysis tools and reader D.O.

## 0.1.5

### Patch Changes

- 016cb73: Add more DEX tools, including remote captures

## 0.1.4

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.3

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.1.2

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.1.1

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/sandbox-container/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# containers-mcp

## 0.2.6

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.2.5

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.2.4

### Patch Changes

- dffbd36: Use proper wrangler deploy in all servers so we get the name and version

## 0.2.3

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.2.2

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.2.1

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.2.0

### Minor Changes

- 2621557: Use new workers:read scope instead of workers:write, as these mcp servers don't require workers write permissions

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/apps/sandbox-container/container/fileUtils.spec.ts:
--------------------------------------------------------------------------------

```typescript
import mime from 'mime'
import mock from 'mock-fs'
import { afterEach, describe, expect, it, vi } from 'vitest'

import { get_file_name_from_path, get_mime_type, list_files_in_directory } from './fileUtils'

vi.mock('mime', () => {
	return {
		default: {
			getType: vi.fn(),
		},
	}
})

afterEach(async () => {
	mock.restore()
	vi.restoreAllMocks()
})

describe('get_file_name_from_path', () => {
	it('strips files/contents', async () => {
		const path = await get_file_name_from_path('/files/contents/cats')
		expect(path).toBe('/cats')
	}),
		it('works if files/contents is not present', async () => {
			const path = await get_file_name_from_path('/dogs')
			expect(path).toBe('/dogs')
		}),
		it('strips a trailing slash', async () => {
			const path = await get_file_name_from_path('/files/contents/birds/')
			expect(path).toBe('/birds')
		})
}),
	describe('list_files_in_directory', () => {
		it('lists the files in a directory', async () => {
			mock({
				testDir: {
					cats: 'aurora, luna',
					dogs: 'penny',
				},
			})
			const listFiles = await list_files_in_directory('testDir')
			expect(listFiles).toEqual(['file:///testDir/cats', 'file:///testDir/dogs'])
		}),
			it('throws an error if path is not a directory', async () => {
				mock({
					testDir: {
						cats: 'aurora, luna',
						dogs: 'penny',
					},
				})
				await expect(async () => await list_files_in_directory('testDir/cats')).rejects.toThrow(
					'Failed to read directory'
				)
			}),
			it('treats empty strings as cwd', async () => {
				mock({
					testDir: {
						cats: 'aurora, luna',
						dogs: 'penny',
					},
				})

				const listFiles = await list_files_in_directory('')
				expect(listFiles).toEqual(['file:///../../../../../../testDir'])
			})
	}),
	describe('get_mime_type', async () => {
		it("provides the natural mime type when not 'inode/directory'", async () => {
			vi.mocked(mime.getType).mockReturnValueOnce('theType')
			const mimeType = await get_mime_type('someFile')
			expect(mimeType).toEqual('theType')
		})
		it("overrides mime type for 'inode/directory'", async () => {
			vi.mocked(mime.getType).mockReturnValueOnce('inode/directory')
			const mimeType = await get_mime_type('someDirectory')
			expect(mimeType).toEqual('text/directory')
		})
	})

```

--------------------------------------------------------------------------------
/apps/dex-analysis/src/warp_diag_reader.ts:
--------------------------------------------------------------------------------

```typescript
import { DurableObject } from 'cloudflare:workers'
import JSZip from 'jszip'

import type { Env } from './dex-analysis.context'

// Helper for reading large WARP diag zip archives.
// Holds the contents in memory between requests from the agent for specific files
// instead of having the worker download the zip on every request.
//
// Each DO represents one remote capture zip
export class WarpDiagReader extends DurableObject<Env> {
	#cache?: { files: string[]; zip: JSZip }

	// List the files in the zip for the agent
	async list(accessToken: string, url: string) {
		const { files } = await this.#getZip(accessToken, url)
		return files
	}

	// Return the contents of a file by path
	async read(accessToken: string, url: string, filepath: string) {
		const { zip } = await this.#getZip(accessToken, url)
		const file = zip.file(filepath)
		const content = await file?.async('text')
		return content
	}

	async #getZip(accessToken: string, url: string) {
		if (this.#cache) {
			return this.#cache
		}

		console.log(`WarpDiagReader fetching `, url)

		const res = await fetch(url, {
			headers: {
				Authorization: `Bearer ${accessToken}`,
			},
		})

		if (res.status !== 200) {
			throw new Error(`failed to download zip, non-200 status code: ${res.status}`)
		}

		const zip = await new JSZip().loadAsync(await res.arrayBuffer())
		const files: string[] = []
		for (const [relativePath, file] of Object.entries(zip.files)) {
			if (!file.dir) {
				files.push(relativePath)
			}
		}

		const cache = { files, zip }
		this.#cache = cache
		return cache
	}
}

async function hashToken(accessToken: string) {
	const hashArr = Array.from(
		new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(accessToken)))
	)
	return hashArr.map((b) => b.toString(16).padStart(2, '0')).join('')
}

// Create unique name based on accessToken hash and download url. In order to read cached zip from memory
// you need to have the same access token that was used to fetch it.
async function readerName(accessToken: string, url: string) {
	return (await hashToken(accessToken)) + url
}

export async function getReader(env: Env, accessToken: string, download: string) {
	const name = await readerName(accessToken, download)
	const id = env.WARP_DIAG_READER.idFromName(name)
	return env.WARP_DIAG_READER.get(id)
}

```

--------------------------------------------------------------------------------
/apps/demo-day/frontend/public/cloudflare.svg:
--------------------------------------------------------------------------------

```
<svg width="531" height="240" viewBox="0 0 531 240" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M364.276 226.805L364.273 226.815L361.598 236.302C361.597 236.305 361.597 236.307 361.596 236.309C361.113 237.921 359.639 239 358.062 239H4.49414C3.17374 239 2.00552 237.981 1.76785 236.575C1.29745 232.723 1 228.886 1 225.057C1 181.893 35.2676 146.875 78.1587 145.596L79.4005 145.559L79.099 144.353C77.5739 138.256 77.146 131.677 77.7417 124.952C80.333 98.8682 101.26 77.9116 127.401 75.3232C142.053 73.966 155.679 78.2521 166.379 86.1874L167.481 87.0051L167.922 85.705C184.598 36.4752 231.241 1 286.199 1C345.788 1 395.645 42.6457 407.99 98.5134L407.993 98.5269L407.997 98.5403C408.24 99.5149 408.147 100.557 407.73 101.656C407.73 101.656 407.73 101.657 407.729 101.657L396.668 130.417L396.668 130.418C392.403 141.573 384.13 151.739 374.079 159.251C364.03 166.762 352.276 171.568 341.092 172.101L147.818 174.606L147.792 174.606L147.766 174.608C145.391 174.762 143.124 176.442 142.386 178.708L142.374 178.745L142.365 178.783C142.011 180.247 142.191 181.794 142.974 182.975C143.77 184.218 145.169 184.982 146.743 184.984C146.746 184.984 146.748 184.984 146.751 184.984L338.283 187.489C348.152 187.956 356.255 191.91 361.006 198.6L361.009 198.603C366.233 205.897 367.495 215.839 364.276 226.805Z" stroke="white" stroke-width="1"/>
<path d="M420.981 105.214H421.032L421.083 105.209C422.708 105.042 424.513 105.041 426.253 105.041C483.434 105.041 530.001 151.584 530.001 208.558C530.001 218.224 528.631 227.635 526.148 236.579L526.145 236.591L526.142 236.604C525.832 237.842 524.712 238.654 523.395 238.654H377.422C376.423 238.654 375.85 237.79 376.193 236.908C376.193 236.907 376.193 236.907 376.193 236.907L379.304 228.962L379.307 228.955C383.572 217.821 391.803 207.666 401.832 200.159C411.862 192.651 423.623 187.843 434.899 187.315L434.911 187.314L477.389 184.809L477.395 184.809C479.77 184.654 482.037 182.974 482.775 180.709L482.782 180.689L482.787 180.669C483.162 179.333 482.96 177.655 482.193 176.45C481.402 175.209 480.011 174.443 478.443 174.432L437.679 171.929L437.672 171.929L437.665 171.928C427.789 171.464 419.679 167.51 414.925 160.817L414.923 160.813C409.698 153.519 408.436 143.577 411.656 132.611L411.657 132.606L419.119 106.698C419.497 105.775 420.265 105.214 420.981 105.214Z" stroke="white" stroke-width="1"/>
</svg>

```

--------------------------------------------------------------------------------
/apps/workers-observability/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# workers-observability

## 0.4.1

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.4.0

### Minor Changes

- dee0a7b: Updated the model for docs search to embeddinggemma-300m

## 0.3.4

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]

## 0.3.3

### Patch Changes

- dffbd36: Use proper wrangler deploy in all servers so we get the name and version

## 0.3.2

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.3.1

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.3.0

### Minor Changes

- f885d07: Add search docs tool to bindings and obs servers

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.2.0

### Minor Changes

- 2621557: Use new workers:read scope instead of workers:write, as these mcp servers don't require workers write permissions

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.4

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- b190e97: fix: set correct entrypoint in wrangler.jsonc
- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/packages/eval-tools/src/runTask.ts:
--------------------------------------------------------------------------------

```typescript
import { type MCPClientManager } from 'agents/mcp/client'
import { generateText, jsonSchema, tool } from 'ai'
import { z } from 'zod'

import type { GenerateTextResult, LanguageModelV1, ToolCallPart, ToolSet } from 'ai'

export async function runTask(
	clientManager: MCPClientManager,
	model: LanguageModelV1,
	input: string
): Promise<{
	promptOutput: string
	fullResult: GenerateTextResult<ToolSet, never>
	toolCalls: ToolCallPart[]
}> {
	const tools = clientManager.listTools()
	const toolSet: ToolSet = tools.reduce((acc, v) => {
		if (!v.inputSchema.properties) {
			v.inputSchema.properties = {}
		}

		acc[v.name] = tool({
			parameters: jsonSchema(v.inputSchema as any),
			description: v.description,
			execute: async (args: any, opts) => {
				try {
					const res = await clientManager.callTool(
						{
							...v,
							arguments: { ...args },
						},
						z.any() as any,
						{ signal: opts.abortSignal }
					)
					return res.content
				} catch (e) {
					console.log('Error calling tool')
					console.log(e)
					return e
				}
			},
		})
		return acc
	}, {} as ToolSet)

	const res = await generateText({
		model,
		system:
			"You are an assistant responsible for evaluating the results of calling various tools. Given the user's query, use the tools available to you to answer the question.",
		tools: toolSet,
		prompt: input,
		maxRetries: 1,
		maxSteps: 10,
	})

	// convert into an LLM readable result so our factuality checker can validate tool calls
	let messagesWithTools = ''
	const toolCalls: ToolCallPart[] = []
	const response = res.response
	const messages = response.messages

	for (const message of messages) {
		for (const messagePart of message.content) {
			if (typeof messagePart === 'string') {
				messagesWithTools += `<message_content type="text">${messagePart}</message_content>`
			} else if (messagePart.type === 'tool-call') {
				messagesWithTools += `<message_content type=${messagePart.type}>
    <tool_name>${messagePart.toolName}</tool_name>
    <tool_arguments>${JSON.stringify(messagePart.args)}</tool_arguments>
</message_content>`
				toolCalls.push(messagePart)
			} else if (messagePart.type === 'text') {
				messagesWithTools += `<message_content type=${messagePart.type}>${messagePart.text}</message_content>`
			}
		}
	}

	return { promptOutput: messagesWithTools, fullResult: res, toolCalls }
}

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/types/kv_namespace.types.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from 'zod'

import type {
	Namespace,
	NamespaceCreateParams,
	NamespaceDeleteParams,
	NamespaceGetParams,
	NamespaceListParams,
	NamespaceUpdateParams,
} from 'cloudflare/resources/kv.mjs'

/**
 * Zod schema for a KV namespace ID.
 */
export const KvNamespaceIdSchema: z.ZodType<Namespace['id']> = z
	.string()
	.describe('The ID of the KV namespace')

/**
 * Zod schema for a KV namespace title.
 */
export const KvNamespaceTitleSchema: z.ZodType<Namespace['title']> = z
	.string()
	.describe('The human-readable name/title of the KV namespace')

/**
 * Zod schema for the optional parameters when listing KV namespaces.
 */
export const KvNamespacesListParamsSchema: z.ZodType<Omit<NamespaceListParams, 'account_id'>> = z
	.object({
		direction: z
			.enum(['asc', 'desc'])
			.optional()
			.describe('Direction to order namespaces (asc/desc)'),
		order: z.enum(['id', 'title']).optional().describe('Field to order namespaces by (id/title)'),
		page: z.number().int().positive().optional().describe('Page number of results (starts at 1)'),
		per_page: z
			.number()
			.int()
			.min(1)
			.max(100)
			.optional()
			.describe('Number of namespaces per page (1-100)'),
	})
	.describe('Optional parameters for listing KV namespaces')

/**
 * Zod schema for parameters needed to create a KV namespace.
 */
export const KvNamespaceCreateParamsSchema: z.ZodType<Omit<NamespaceCreateParams, 'account_id'>> = z
	.object({
		title: KvNamespaceTitleSchema,
	})
	.describe('Parameters for creating a KV namespace')

/**
 * Zod schema for parameters needed to delete a KV namespace.
 */
export const KvNamespaceDeleteParamsSchema: z.ZodType<Omit<NamespaceDeleteParams, 'account_id'>> = z
	.object({
		namespace_id: KvNamespaceIdSchema,
	})
	.describe('Parameters for deleting a KV namespace')

/**
 * Zod schema for parameters needed to get a KV namespace.
 */
export const KvNamespaceGetParamsSchema: z.ZodType<Omit<NamespaceGetParams, 'account_id'>> = z
	.object({
		namespace_id: KvNamespaceIdSchema,
	})
	.describe('Parameters for getting a KV namespace')

/**
 * Zod schema for parameters needed to update a KV namespace.
 */
export const KvNamespaceUpdateParamsSchema: z.ZodType<Omit<NamespaceUpdateParams, 'account_id'>> = z
	.object({
		namespace_id: KvNamespaceIdSchema,
		title: KvNamespaceTitleSchema,
	})
	.describe('Parameters for updating a KV namespace')

```

--------------------------------------------------------------------------------
/packages/tools/src/changesets.spec.ts:
--------------------------------------------------------------------------------

```typescript
import { program } from '@commander-js/extra-typings'
import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest'

import { getPublishedPackages } from './changesets'

describe('getPublishedPackages', () => {
	const fixturesDir = path.join(__dirname, 'test/fixtures/changesets')
	const fixture = (name: string) => path.join(fixturesDir, name)

	beforeAll(() => {
		// throw errors instead of calling process.exit(1)
		// within program.error() is called by cliError()
		program.exitOverride((e) => {
			throw e
		})
	})
	afterEach(() => {
		vi.unstubAllEnvs()
	})

	it('should read and parse valid published packages', async () => {
		vi.stubEnv('RUNNER_TEMP', fixture('valid'))

		const result = await getPublishedPackages()

		expect(result).toStrictEqual([
			{ name: 'package-a', version: '1.0.0' },
			{ name: 'package-b', version: '2.1.3' },
		])
	})

	it('should throw error when RUNNER_TEMP is not set', async () => {
		vi.stubEnv('RUNNER_TEMP', undefined)

		await expect(getPublishedPackages()).rejects.toThrowErrorMatchingInlineSnapshot(
			`[CommanderError: error: ✖ $RUNNER_TEMP is not set]`
		)
	})

	it('should throw error when RUNNER_TEMP is empty', async () => {
		vi.stubEnv('RUNNER_TEMP', '')

		await expect(getPublishedPackages()).rejects.toThrowErrorMatchingInlineSnapshot(
			`[CommanderError: error: ✖ $RUNNER_TEMP is empty]`
		)
	})

	it('should throw error when published packages file is not found', async () => {
		vi.stubEnv('RUNNER_TEMP', fixture('empty'))

		await expect(getPublishedPackages()).rejects.toThrowErrorMatchingInlineSnapshot(
			`[CommanderError: error: No published packages file found at: ${fixture('empty/published-packages.json')}]`
		)
	})

	it('should throw error when published packages JSON is invalid', async () => {
		vi.stubEnv('RUNNER_TEMP', fixture('invalid-json'))

		await expect(getPublishedPackages()).rejects.toThrowErrorMatchingInlineSnapshot(
			`[Error: Failed to parse published packages: SyntaxError: Unexpected token 'h', "this is not"... is not valid JSON]`
		)
	})

	it('should throw error when published packages schema is invalid', async () => {
		vi.stubEnv('RUNNER_TEMP', fixture('invalid-schema'))

		await expect(getPublishedPackages()).rejects.toThrowErrorMatchingInlineSnapshot(`
			[Error: Failed to parse published packages: ✖ Invalid input: expected string, received number
			  → at [0].version]
		`)
	})
})

```

--------------------------------------------------------------------------------
/apps/workers-bindings/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# workers-bindings

## 0.4.1

### Patch Changes

- 43f493d: Update agent + modelcontextprotocol deps
- Updated dependencies [43f493d]
  - @repo/[email protected]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.4.0

### Minor Changes

- dee0a7b: Updated the model for docs search to embeddinggemma-300m

## 0.3.4

### Patch Changes

- 24dd872: feat: Add MCP tool titles and hints to all Cloudflare tools
- Updated dependencies [24dd872]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.3.3

### Patch Changes

- dffbd36: Use proper wrangler deploy in all servers so we get the name and version

## 0.3.2

### Patch Changes

- 7422e71: Update MCP sdk
- Updated dependencies [7422e71]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.3.1

### Patch Changes

- cc6d41f: Update agents deps & modelcontextprotocol
- Updated dependencies [1833c6d]
- Updated dependencies [cc6d41f]
  - @repo/[email protected]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.3.0

### Minor Changes

- f885d07: Add search docs tool to bindings and obs servers

### Patch Changes

- Updated dependencies [f885d07]
  - @repo/[email protected]

## 0.2.0

### Minor Changes

- 2621557: Use new workers:read scope instead of workers:write, as these mcp servers don't require workers write permissions

### Patch Changes

- Updated dependencies [83e2d19]
  - @repo/[email protected]

## 0.1.0

### Minor Changes

- 6cf52a6: Support AOT tokens

### Patch Changes

- 0fc4439: Update agents and modelcontext dependencies
- Updated dependencies [6cf52a6]
- Updated dependencies [0fc4439]
  - @repo/[email protected]
  - @repo/[email protected]
  - @repo/[email protected]

## 0.0.3

### Patch Changes

- 3677a18: Remove extraneous log
- Updated dependencies [3677a18]
  - @repo/[email protected]

## 0.0.2

### Patch Changes

- 86c2e4f: Add API token passthrough auth
- Updated dependencies [86c2e4f]
  - @repo/[email protected]

## 0.0.1

### Patch Changes

- cf3771b: chore: add suffixes to common files in apps and packages

  It can be confusing switching between 16 files named 'index.ts', or 3 files named workers.ts. This change renames common files to have suffixes such as .types.ts, .api.ts, etc. to make it easier to work across files in the monorepo.

- Updated dependencies [cf3771b]
  - @repo/[email protected]
  - @repo/[email protected]
  - @repo/[email protected]

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/api/workers-observability.api.ts:
--------------------------------------------------------------------------------

```typescript
import { env } from 'cloudflare:workers'

import { fetchCloudflareApi } from '../cloudflare-api'
import {
	zKeysResponse,
	zReturnedQueryRunResult,
	zValuesResponse,
} from '../types/workers-logs.types'
import { V4Schema } from '../v4-api'

import type { z } from 'zod'
import type { zKeysRequest, zQueryRunRequest, zValuesRequest } from '../types/workers-logs.types'

type QueryRunRequest = z.infer<typeof zQueryRunRequest>

function fixTimeframe(timeframe: QueryRunRequest['timeframe']) {
	return {
		from: new Date(timeframe.from).getTime(),
		to: new Date(timeframe.to).getTime(),
	}
}

export async function queryWorkersObservability(
	apiToken: string,
	accountId: string,
	query: QueryRunRequest
): Promise<z.infer<typeof zReturnedQueryRunResult> | null> {
	// @ts-expect-error We don't have actual env in this package
	const environment = env.ENVIRONMENT
	const data = await fetchCloudflareApi({
		endpoint: '/workers/observability/telemetry/query',
		accountId,
		apiToken,
		responseSchema: V4Schema(zReturnedQueryRunResult),
		options: {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
				'workers-observability-origin': `workers-observability-mcp-${environment}`,
			},
			body: JSON.stringify({ ...query, timeframe: fixTimeframe(query.timeframe) }),
		},
	})

	return data.result
}

type QueryKeysRequest = z.infer<typeof zKeysRequest>
export async function handleWorkerLogsKeys(
	apiToken: string,
	accountId: string,
	keysQuery: QueryKeysRequest
): Promise<zKeysResponse> {
	const data = await fetchCloudflareApi({
		endpoint: '/workers/observability/telemetry/keys',
		accountId,
		apiToken,
		responseSchema: V4Schema(zKeysResponse),
		options: {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
			},
			body: JSON.stringify({ ...keysQuery, timeframe: fixTimeframe(keysQuery.timeframe) }),
		},
	})

	return data.result || []
}

export async function handleWorkerLogsValues(
	apiToken: string,
	accountId: string,
	valuesQuery: z.infer<typeof zValuesRequest>
): Promise<z.infer<typeof zValuesResponse> | null> {
	const data = await fetchCloudflareApi({
		endpoint: '/workers/observability/telemetry/values',
		accountId,
		apiToken,
		responseSchema: V4Schema(zValuesResponse),
		options: {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
			},
			body: JSON.stringify({ ...valuesQuery, timeframe: fixTimeframe(valuesQuery.timeframe) }),
		},
	})

	return data.result
}

```

--------------------------------------------------------------------------------
/packages/eval-tools/src/scorers.ts:
--------------------------------------------------------------------------------

```typescript
import { generateObject } from 'ai'
import { z } from 'zod'

import { factualityModel } from './test-models'

import type { ScoreFn } from 'vitest-evals'

/**
 * Checks the factuality of a submission, using
 * OpenAI's GPT-4o model.
 */
export const checkFactuality: ScoreFn = async ({ input, expected, output }) => {
	const { model } = factualityModel
	const { object } = await generateObject({
		model,
		/**
		 * Prompt taken from autoevals:
		 *
		 * {@link https://github.com/braintrustdata/autoevals/blob/5aa20a0a9eb8fc9e07e9e5722ebf71c68d082f32/templates/factuality.yaml}
		 */
		prompt: `
        You are comparing a submitted answer to an expert's rubric on a given question. Here is the data:
        [BEGIN DATA]
        ************
        [Question]: ${input}
        ************
        [Expert Rubric]: ${expected}
        ************
        [Submission]: ${output}
        ************
        [END DATA]

		Submissions contain message metadata inside of the <message_content> XML tags. 
		The attribute \`type=text\` indicates text content. The attribute \`type=tool-call\` indicates a tool call. 
		Use this metadata to determine the accuracy of the response.
  
        Compare the factual content of the submitted answer with the expert's answer rubric. Ignore any differences in style, grammar, or punctuation.
        The submitted answer may either be a subset or superset of the expert's expected answer, or it may conflict with it. Determine which case applies. Answer the question by selecting one of the following options:
        (A) The submitted answer is a subset of the answer the expert's rubric describes and is fully consistent with it.
        (B) The submitted answer is a superset of the answer the expert's rubric describes and is fully consistent with it.
        (C) The submitted answer contains all the same details of the answer the expert's rubric describes.
        (D) There is a disagreement between the submitted answer and the expert's rubric.
        (E) The answers differ, but these differences don't matter from the perspective of factuality.
      `,
		schema: z.object({
			answer: z.enum(['A', 'B', 'C', 'D', 'E']).describe('Your selection.'),
			rationale: z.string().describe('Why you chose this answer. Be very detailed.'),
		}),
	})

	/**
	 * LLM's are well documented at being poor at generating
	 */
	const scores = {
		A: 0.4,
		B: 1,
		C: 1,
		D: 0,
		E: 1,
	}

	return {
		score: scores[object.answer],
		metadata: {
			rationale: object.rationale,
		},
	}
}

```

--------------------------------------------------------------------------------
/apps/docs-autorag/src/tools/docs-autorag.tools.ts:
--------------------------------------------------------------------------------

```typescript
import { type EmbeddedResource } from '@modelcontextprotocol/sdk/types.js'
import mime from 'mime'
import { z } from 'zod'

import type { CloudflareDocumentationMCP } from '../docs-autorag.app'

/**
 * Registers the docs search tool with the MCP server
 * @param agent The MCP server instance
 */
export function registerDocsTools(agent: CloudflareDocumentationMCP) {
	// Register the worker logs analysis tool by worker name
	agent.server.tool(
		'search_cloudflare_documentation',
		`Search the Cloudflare documentation.

		You should use this tool when:
		- A user asks questions about Cloudflare products (Workers, Developer Platform, Zero Trust, CDN, etc)
		- A user requests information about a Cloudflare feature
		- You are unsure of how to use some Cloudflare functionality
		- You are writing Cloudflare Workers code and need to look up Workers-specific documentation

		This tool returns a number of results from a vector database. These are embedded as resources in the response and are plaintext documents in a variety of formats.
		`,
		{
			// partially pulled from autorag query optimization example
			query: z.string().describe(`Search query. The query should:
1. Identify the core concepts and intent
2. Add relevant synonyms and related terms
3. Remove irrelevant filler words
4. Structure the query to emphasize key terms
5. Include technical or domain-specific terminology if applicable`),
			scoreThreshold: z
				.number()
				.min(0)
				.max(1)
				.optional()
				.describe('A score threshold (0-1) for which matches should be included.'),
			maxNumResults: z
				.number()
				.default(10)
				.optional()
				.describe('The maximum number of results to return.'),
		},
		async (params) => {
			// we don't need "rewrite query" OR aiSearch because an LLM writes the query and formats the output for us.
			const result = await agent.env.AI.autorag(agent.env.AUTORAG_NAME).search({
				query: params.query,
				ranking_options: params.scoreThreshold
					? {
							score_threshold: params.scoreThreshold,
						}
					: undefined,
				max_num_results: params.maxNumResults,
			})

			const resources: EmbeddedResource[] = result.data.map((result) => {
				const content = result.content.reduce((acc, contentPart) => {
					return acc + contentPart.text
				}, '')
				return {
					type: 'resource',
					resource: {
						uri: `docs://${result.filename}`,
						mimeType: mime.getType(result.filename) ?? 'text/plain',
						text: content,
					},
				}
			})

			return {
				content: resources,
			}
		}
	)
}

```

--------------------------------------------------------------------------------
/apps/radar/src/tools/url-scanner.tools.ts:
--------------------------------------------------------------------------------

```typescript
import { getCloudflareClient } from '@repo/mcp-common/src/cloudflare-api'
import { getProps } from '@repo/mcp-common/src/get-props'
import { pollUntilReady } from '@repo/mcp-common/src/poll'

import { CreateScanResult, UrlParam } from '../types/url-scanner'

import type { RadarMCP } from '../radar.app'

const MAX_WAIT_SECONDS = 30
const INTERVAL_SECONDS = 2

export function registerUrlScannerTools(agent: RadarMCP) {
	agent.server.tool(
		'scan_url',
		'Submit a URL to scan',
		{
			url: UrlParam,
		},
		async ({ url }) => {
			const accountId = await agent.getActiveAccountId()
			if (!accountId) {
				return {
					content: [
						{
							type: 'text',
							text: 'No currently active accountId. Try listing your accounts (accounts_list) and then setting an active account (set_active_account)',
						},
					],
				}
			}

			try {
				const props = getProps(agent)
				const client = getCloudflareClient(props.accessToken)

				// Search if there are recent scans for the URL
				const scans = await client.urlScanner.scans.list({
					account_id: accountId,
					q: `page.url:"${url}"`,
				})

				let scanId = scans.results.length > 0 ? scans.results[0]._id : null

				if (!scanId) {
					// Submit scan
					// TODO theres an issue (reported) with this method in the cloudflare TS lib
					// const scan = await (client.urlScanner.scans.create({ account_id, url: "https://www.example.com" }, { headers })).withResponse()

					const res = await fetch(
						`https://api.cloudflare.com/client/v4/accounts/${accountId}/urlscanner/v2/scan`,
						{
							method: 'POST',
							headers: {
								Authorization: `Bearer ${props.accessToken}`,
							},
							body: JSON.stringify({ url }),
						}
					)

					if (!res.ok) {
						throw new Error('Failed to submit scan')
					}

					const scan = CreateScanResult.parse(await res.json())
					scanId = scan?.uuid
				}

				const r = await pollUntilReady({
					taskFn: () => client.urlScanner.scans.get(scanId, { account_id: accountId }),
					intervalSeconds: INTERVAL_SECONDS,
					maxWaitSeconds: MAX_WAIT_SECONDS,
				})

				return {
					content: [
						{
							type: 'text',
							text: JSON.stringify({
								result: { verdicts: r.verdicts, stats: r.stats, page: r.page }, // TODO select what is more relevant, or add a param to allow the agent to select a set of metrics
							}),
						},
					],
				}
			} catch (error) {
				return {
					content: [
						{
							type: 'text',
							text: `Error scanning URL: ${error instanceof Error && error.message}`,
						},
					],
				}
			}
		}
	)
}

```

--------------------------------------------------------------------------------
/apps/demo-day/frontend/public/cloudflare_logo.svg:
--------------------------------------------------------------------------------

```
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 651.29 94.76"><defs><style>.cls-1{fill:#ffffff;}.cls-2{fill:#ffffff;}</style></defs><path class="cls-1" d="M143.05,93.42l1.07-3.71c1.27-4.41.8-8.48-1.34-11.48-2-2.76-5.26-4.38-9.25-4.57L58,72.7a1.47,1.47,0,0,1-1.35-2,2,2,0,0,1,1.75-1.34l76.26-1c9-.41,18.84-7.75,22.27-16.71l4.34-11.36a2.68,2.68,0,0,0,.18-1,3.31,3.31,0,0,0-.06-.54,49.67,49.67,0,0,0-95.49-5.14,22.35,22.35,0,0,0-35,23.42A31.73,31.73,0,0,0,.34,93.45a1.47,1.47,0,0,0,1.45,1.27l139.49,0h0A1.83,1.83,0,0,0,143.05,93.42Z"/><path class="cls-2" d="M168.22,41.15q-1,0-2.1.06a.88.88,0,0,0-.32.07,1.17,1.17,0,0,0-.76.8l-3,10.26c-1.28,4.41-.81,8.48,1.34,11.48a11.65,11.65,0,0,0,9.24,4.57l16.11,1a1.44,1.44,0,0,1,1.14.62,1.5,1.5,0,0,1,.17,1.37,2,2,0,0,1-1.75,1.34l-16.73,1c-9.09.42-18.88,7.75-22.31,16.7l-1.21,3.16a.9.9,0,0,0,.79,1.22h57.63A1.55,1.55,0,0,0,208,93.63a41.34,41.34,0,0,0-39.76-52.48Z"/><polygon points="273.03 59.66 282.56 59.66 282.56 85.72 299.23 85.72 299.23 94.07 273.03 94.07 273.03 59.66"/><path d="M309.11,77v-.09c0-9.88,8-17.9,18.58-17.9s18.48,7.92,18.48,17.8v.1c0,9.88-8,17.89-18.58,17.89S309.11,86.85,309.11,77m27.33,0v-.09c0-5-3.59-9.29-8.85-9.29s-8.7,4.22-8.7,9.19v.1c0,5,3.59,9.29,8.8,9.29s8.75-4.23,8.75-9.2"/><path d="M357.84,79V59.66h9.69V78.78c0,5,2.5,7.33,6.34,7.33s6.34-2.26,6.34-7.08V59.66h9.68V78.73c0,11.11-6.34,16-16.12,16s-15.93-5-15.93-15.73"/><path d="M404.49,59.66h13.27c12.29,0,19.42,7.08,19.42,17v.1c0,9.93-7.23,17.3-19.61,17.3H404.49Zm13.42,26c5.7,0,9.49-3.15,9.49-8.71v-.09c0-5.51-3.79-8.71-9.49-8.71H414V85.62Z"/><polygon points="451.04 59.66 478.56 59.66 478.56 68.02 460.58 68.02 460.58 73.87 476.85 73.87 476.85 81.78 460.58 81.78 460.58 94.07 451.04 94.07 451.04 59.66"/><polygon points="491.84 59.66 501.37 59.66 501.37 85.72 518.04 85.72 518.04 94.07 491.84 94.07 491.84 59.66"/><path d="M543,59.42h9.19L566.8,94.07H556.58l-2.51-6.14H540.79l-2.45,6.14h-10Zm8.35,21.08-3.83-9.78L543.6,80.5Z"/><path d="M579.08,59.66h16.27c5.27,0,8.9,1.38,11.21,3.74a10.64,10.64,0,0,1,3.05,8v.1a10.88,10.88,0,0,1-7.08,10.57l8.21,12h-11L592.8,83.65h-4.18V94.07h-9.54Zm15.83,16.52c3.25,0,5.12-1.58,5.12-4.08V72c0-2.71-2-4.08-5.17-4.08h-6.24v8.26Z"/><polygon points="623.37 59.66 651.05 59.66 651.05 67.77 632.81 67.77 632.81 72.98 649.33 72.98 649.33 80.5 632.81 80.5 632.81 85.96 651.29 85.96 651.29 94.07 623.37 94.07 623.37 59.66"/><path d="M252.15,81a8.44,8.44,0,0,1-7.88,5.16c-5.22,0-8.8-4.33-8.8-9.29v-.1c0-5,3.49-9.2,8.7-9.2a8.64,8.64,0,0,1,8.18,5.71h10C260.79,65.09,253.6,59,244.27,59c-10.62,0-18.58,8-18.58,17.9V77c0,9.88,7.86,17.8,18.48,17.8,9.08,0,16.18-5.88,18.05-13.76Z"/></svg>
```

--------------------------------------------------------------------------------
/apps/sandbox-container/evals/files.eval.ts:
--------------------------------------------------------------------------------

```typescript
import { assert, expect } from 'vitest'
import { describeEval } from 'vitest-evals'
import { z } from 'zod'

import { runTask } from '@repo/eval-tools/src/runTask'
import { checkFactuality } from '@repo/eval-tools/src/scorers'
import { eachModel } from '@repo/eval-tools/src/test-models'

import { initializeClient } from './utils'

eachModel('$modelName', ({ model }) => {
	describeEval('Runs container file write', {
		data: async () => [
			{
				input: 'write a file named test.txt containing the text "asdf"',
				expected: 'The container_file_write tool was called and the file\'s content is "asdf"',
			},
		],
		task: async (input) => {
			const client = await initializeClient()
			const { promptOutput } = await runTask(client, model, input)
			const fileRead = client.listTools().find((tool) => {
				if (tool.name === 'container_file_read') {
					return tool
				}
			})

			assert(fileRead !== undefined)
			const result = await client.callTool(
				{
					...fileRead,
					arguments: {
						args: { path: 'file://test.txt' },
					},
				},
				z.any() as any,
				{}
			)

			expect(result.content).toStrictEqual([
				{
					type: 'resource',
					resource: {
						uri: 'file://test.txt',
						mimeType: 'text/plain',
						text: 'asdf',
					},
				},
			])

			return promptOutput
		},
		scorers: [checkFactuality],
		threshold: 1,
		timeout: 60000,
	})

	describeEval('Runs container file delete', {
		data: async () => [
			{
				input: 'write a file named test.txt, then delete it',
				expected:
					'The container_file_write tool was called and then the container_file_delete tool was called with the same parameters',
			},
		],
		task: async (input) => {
			const client = await initializeClient()
			const { promptOutput, toolCalls } = await runTask(client, model, input)

			const toolArgs = toolCalls.find((tool) => {
				return tool.toolName === 'container_file_write' ? tool : undefined
			})?.args as { args: { path: string } } | undefined

			assert(toolArgs !== undefined)
			expect(toolCalls).toEqual(
				expect.arrayContaining([
					expect.objectContaining({
						type: 'tool-call',
						toolName: 'container_file_write',
						args: {
							args: expect.objectContaining({
								path: toolArgs.args.path,
							}),
						},
					}),
				])
			)

			expect(toolCalls).toEqual(
				expect.arrayContaining([
					expect.objectContaining({
						type: 'tool-call',
						toolName: 'container_file_delete',
						args: {
							args: expect.objectContaining({
								path: toolArgs.args.path,
							}),
						},
					}),
				])
			)

			return promptOutput
		},
		scorers: [checkFactuality],
		threshold: 1,
		timeout: 60000,
	})
})

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/tools/account.tools.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from 'zod'

import { handleAccountsList } from '../api/account.api'
import { getCloudflareClient } from '../cloudflare-api'
import { getProps } from '../get-props'

import type { CloudflareMcpAgent } from '../types/cloudflare-mcp-agent.types'

export function registerAccountTools(agent: CloudflareMcpAgent) {
	// Tool to list all accounts
	agent.server.tool(
		'accounts_list',
		'List all accounts in your Cloudflare account',
		{},
		{
			title: 'List accounts',
			annotations: {
				readOnlyHint: true,
			},
		},
		async () => {
			try {
				const props = getProps(agent)
				const results = await handleAccountsList({
					client: getCloudflareClient(props.accessToken),
				})
				// Sort accounts by created_on date (newest first)
				const accounts = results
					// order by created_on desc ( newest first )
					.sort((a, b) => {
						if (!a.created_on) return 1
						if (!b.created_on) return -1
						return new Date(b.created_on).getTime() - new Date(a.created_on).getTime()
					})
					// Remove fields not needed by the LLM
					.map((account) => {
						return {
							id: account.id,
							name: account.name,
							created_on: account.created_on,
						}
					})

				return {
					content: [
						{
							type: 'text',
							text: JSON.stringify({
								accounts,
								count: accounts.length,
							}),
						},
					],
				}
			} catch (e) {
				agent.server.recordError(e)
				return {
					content: [
						{
							type: 'text',
							text: `Error listing accounts: ${e instanceof Error && e.message}`,
						},
					],
				}
			}
		}
	)

	// Only register set_active_account tool when user token is provided, as it doesn't make sense to expose
	// this tool for account scoped tokens, given that they're scoped to a single account
	if (getProps(agent).type === 'user_token') {
		const activeAccountIdParam = z
			.string()
			.describe(
				'The accountId present in the users Cloudflare account, that should be the active accountId.'
			)
		agent.server.tool(
			'set_active_account',
			'Set active account to be used for tool calls that require accountId',
			{
				activeAccountIdParam,
			},
			{
				title: 'Set active account',
				annotations: {
					readOnlyHint: false,
					destructiveHint: false,
				},
			},
			async (params) => {
				try {
					const { activeAccountIdParam: activeAccountId } = params
					await agent.setActiveAccountId(activeAccountId)
					return {
						content: [
							{
								type: 'text',
								text: JSON.stringify({
									activeAccountId,
								}),
							},
						],
					}
				} catch (e) {
					agent.server.recordError(e)
					return {
						content: [
							{
								type: 'text',
								text: `Error setting activeAccountID: ${e instanceof Error && e.message}`,
							},
						],
					}
				}
			}
		)
	}
}

```

--------------------------------------------------------------------------------
/apps/sandbox-container/server/prompts.ts:
--------------------------------------------------------------------------------

```typescript
export const BASE_INSTRUCTIONS = /* markdown */ `
# Container MCP Agent

The Container MCP Agent provides access to a sandboxed container environment. This is an ephemeral container and has access to the internet.

The container is an Ubuntu 20.04 base image with the following packages installed:
- curl
- git
- net-tools
- build-essential
- nodejs
- npm
- python3
- python3-pip

If necessary, you may install additional packages.

You are given a working directory in which you can create or delete files and execute commands as described below.

If you're using python, ALWAYS use \`python3\` instead of \`python\`. ALWAYS make sure to install dependencies, as they won't be installed ahead of time.

## Resources

The primary resource in this image is the \`container_files\` resource. 
This is a dynamic resource, which provides a list of files defined by \`file://{filepath}\`, where filepath is relative to the root working directory you are in. 

The \`container_files_list\` allows you to list all file resources in your working directory. Content is omitted from the response of this tool.

You can read files in the container using the \`container_file_read\` tool. The contents are returned as a text blob with their associated mime type if it is text, 
or a base64 encoded blob for binary files.

Directories have the special mime type \`inode/directory\`. If \`container_file_read\` is called on a directory, it returns the contents of the directory as a list of resource URIs.

AVOID manually reading or writing files using the \`container_exec\` tool. You should prefer the dedicated file resources and tools to interact with the filesystem as it is less error prone. 

## Tools

To manage container lifecycle, use the \`container_initialize\` tool. If you run into errors where you can't connect to the container, attempt to restart the container with the same \`container_initialize\` tool. If that doesn't work, the system is probably overloaded.

You can execute actions in the container using the \`container_exec\` tool. By default, stdout is returned back as a string.
To write a file, use the \`container_file_write\` tool. To delete a file, use the \`container_file_delete\` tool.

The \`container_files_list\` allows you to list file resources. Content is omitted from the response of this tool and all mimeTypes are \`text/plain\` even if the file ending suggests otherwise.
If you want to get the file contents of a file resource, use \`container_file_read\`, which will return the file contents.

If after calling a tool, you receive an error that a cloudchamber instance cannot be provided, just stop attempting to answer and request that the user attempt to try again later.

If you run into issues, do not attempt to retry after 3 tries unless the user prompts you to. Instead direct the user to report an issue at: https://github.com/cloudflare/mcp-server-cloudflare
`

```

--------------------------------------------------------------------------------
/packages/mcp-common/src/types/workers-builds.types.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from 'zod'

export type BuildDetails = z.infer<typeof BuildDetails>
export const BuildDetails = z.object({
	// TODO: Maybe remove fields we don't need to reduce surface area of things we need to update
	build_uuid: z.string(),
	status: z.string(),
	build_outcome: z.string().nullable(),
	created_on: z.coerce.date(),
	modified_on: z.coerce.date(),
	initializing_on: z.coerce.date().nullable(),
	running_on: z.coerce.date().nullable(),
	stopped_on: z.coerce.date().nullable(),
	trigger: z.object({
		trigger_uuid: z.string(),
		external_script_id: z.string(),
		trigger_name: z.string(),
		build_command: z.string(),
		deploy_command: z.string(),
		root_directory: z.string(),
		branch_includes: z.array(z.string()),
		branch_excludes: z.array(z.string()),
		path_includes: z.array(z.string()),
		path_excludes: z.array(z.string()),
		build_caching_enabled: z.boolean(),
		created_on: z.coerce.date(),
		modified_on: z.coerce.date(),
		deleted_on: z.coerce.date().nullable(),
		repo_connection: z.object({
			repo_connection_uuid: z.string(),
			repo_id: z.string(),
			repo_name: z.string(),
			provider_type: z.string(),
			provider_account_id: z.string(),
			provider_account_name: z.string(),
			created_on: z.coerce.date(),
			modified_on: z.coerce.date(),
			deleted_on: z.coerce.date().nullable(),
		}),
	}),
	build_trigger_metadata: z.object({
		build_trigger_source: z.string(),
		branch: z.string(),
		commit_hash: z.string(),
		commit_message: z.string(),
		author: z.string(),
		build_command: z.string(),
		deploy_command: z.string(),
		root_directory: z.string(),
		build_token_uuid: z.string(),
		environment_variables: z.record(
			z.string(),
			z.object({
				is_secret: z.boolean(),
				created_on: z.coerce.date(),
				value: z.string().nullable(),
			})
		),
		repo_name: z.string(),
		provider_account_name: z.string(),
		provider_type: z.string(),
	}),
	pull_request: z.unknown(),
})

/**
 * GET /builds/workers/:external_script_id/builds
 */
export type ListBuildsByScriptResult = z.infer<typeof ListBuildsByScriptResult>
export const ListBuildsByScriptResult = z.array(BuildDetails)

export type ListBuildsByScriptResultInfo = z.infer<typeof ListBuildsByScriptResultInfo>
export const ListBuildsByScriptResultInfo = z.object({
	next_page: z.boolean(),
	page: z.number(),
	per_page: z.number(),
	count: z.number(),
	total_count: z.number(),
	total_pages: z.number(),
})

export type GetBuildResult = z.infer<typeof GetBuildResult>
export const GetBuildResult = BuildDetails

export type LogLine = z.infer<typeof LogLine>
export const LogLine = z.tuple([
	z.coerce.date().describe('line timestamp'),
	z.string().describe('line message'),
])

export type GetBuildLogsResult = z.infer<typeof GetBuildLogsResult>
export const GetBuildLogsResult = z.object({
	cursor: z.string().optional().describe('pagination cursor'),
	truncated: z.boolean(),
	lines: z.array(LogLine),
})

```

--------------------------------------------------------------------------------
/apps/demo-day/frontend/public/stripe.svg:
--------------------------------------------------------------------------------

```
<svg width="498" height="498" viewBox="0 0 498 498" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_1171_29)">
<rect x="5" y="1" width="488" height="488" rx="77" stroke="white" stroke-width="2" shape-rendering="crispEdges"/>
</g>
<g filter="url(#filter1_d_1171_29)">
<path d="M254.68 96.082C281.995 96.0821 308.964 100.336 336.251 111.109V187.169C311.044 173.904 279.661 166.483 254.68 166.482C245.797 166.482 238.504 167.735 233.402 170.75C228.213 173.817 225.379 178.659 225.379 185.499C225.379 190.498 227.517 194.558 231.143 197.993C234.74 201.401 239.824 204.219 245.808 206.81C251.8 209.404 258.78 211.804 266.211 214.338C273.655 216.876 281.566 219.553 289.477 222.711C305.304 229.03 321.028 237.241 332.817 249.986C344.395 262.503 352.235 279.455 352.556 303.463L352.565 304.611C352.565 334.175 340.793 357.4 320.487 373.259C300.152 389.14 271.174 397.695 236.7 397.695C208.383 397.695 177.442 392.12 146.805 379.016V301.951C174.624 316.941 209.332 327.962 236.7 327.962C246.077 327.962 254.276 326.71 260.162 323.414C263.121 321.757 265.51 319.575 267.153 316.771C268.797 313.966 269.663 310.595 269.663 306.61C269.663 296.03 261.196 289.259 249.324 283.608C243.345 280.763 236.384 278.146 228.973 275.449C221.547 272.748 213.664 269.965 205.778 266.772C190.001 260.386 174.342 252.41 162.628 240.368C150.947 228.36 143.143 212.261 143.143 189.502C143.143 160.251 154.263 136.938 173.701 120.919C193.162 104.881 221.05 96.082 254.68 96.082Z" stroke="white" stroke-width="2" shape-rendering="crispEdges"/>
</g>
<defs>
<filter id="filter0_d_1171_29" x="0" y="0" width="498" height="498" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1171_29"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1171_29" result="shape"/>
</filter>
<filter id="filter1_d_1171_29" x="138.143" y="95.082" width="219.422" height="311.613" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1171_29"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1171_29" result="shape"/>
</filter>
</defs>
</svg>

```
Page 2/25FirstPrevNextLast