├── .changeset ├── README.md └── config.json ├── .dockerignore ├── .editorconfig ├── .eslintrc.cjs ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md ├── actions │ └── setup │ │ └── action.yml └── workflows │ ├── branches.yml │ ├── main.yml │ └── release.yml ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc.cjs ├── .syncpackrc.cjs ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── apps ├── ai-gateway │ ├── .dev.vars.example │ ├── .eslintrc.cjs │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── README.md │ ├── package.json │ ├── 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 │ ├── README.md │ ├── package.json │ ├── 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 │ ├── README.md │ ├── package.json │ ├── 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 │ ├── README.md │ ├── package.json │ ├── 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 │ ├── README.md │ ├── package.json │ ├── 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.svg │ │ │ ├── cloudflare_logo.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 │ ├── README.md │ ├── package.json │ ├── 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 │ ├── README.md │ ├── package.json │ ├── 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 │ ├── README.md │ ├── package.json │ ├── 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 │ ├── README.md │ ├── package.json │ ├── 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 │ ├── README.md │ ├── package.json │ ├── 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 │ ├── README.md │ ├── package.json │ ├── 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 │ ├── README.md │ ├── package.json │ ├── 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 │ ├── CONTRIBUTING.md │ ├── Dockerfile │ ├── README.md │ ├── container │ │ ├── fileUtils.spec.ts │ │ ├── fileUtils.ts │ │ ├── sandbox.container.app.ts │ │ └── tsconfig.json │ ├── evals │ │ ├── exec.eval.ts │ │ ├── files.eval.ts │ │ ├── initialize.eval.ts │ │ └── utils.ts │ ├── package.json │ ├── 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 │ ├── README.md │ ├── evals │ │ ├── accounts.eval.ts │ │ ├── hyperdrive.eval.ts │ │ ├── kv_namespaces.eval.ts │ │ ├── types.d.ts │ │ └── utils.ts │ ├── package.json │ ├── 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 │ ├── README.md │ ├── package.json │ ├── 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 │ ├── README.md │ ├── package.json │ ├── 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 ├── implementation-guides ├── evals.md ├── tools.md └── type-validators.md ├── package.json ├── packages ├── eslint-config │ ├── CHANGELOG.md │ ├── README.md │ ├── default.cjs │ └── package.json ├── 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 │ ├── README.md │ ├── package.json │ ├── src │ │ ├── api-handler.ts │ │ ├── api-token-mode.ts │ │ ├── api │ │ │ ├── account.api.ts │ │ │ ├── cf1-integration.api.ts │ │ │ ├── workers-builds.api.ts │ │ │ ├── workers-observability.api.ts │ │ │ ├── workers.api.ts │ │ │ └── zone.api.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 │ │ ├── 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 │ ├── CHANGELOG.md │ ├── README.md │ ├── 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 │ ├── package.json │ ├── 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 ├── tsconfig.json ├── turbo.json └── vitest.workspace.ts /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "restricted", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [], 11 | "privatePackages": { 12 | "version": true, 13 | "tag": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | **/node_modules/ 2 | **/.gitignore 3 | **/README.md 4 | **/.vscode/ 5 | **/Dockerfile 6 | **/out/ -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = tab 8 | indent_size = 2 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | 14 | [*.{yml,yaml,mdx}] 15 | indent_style = space 16 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | // This configuration only applies to the package manager root. 2 | /** @type {import("eslint").Linter.Config} */ 3 | module.exports = { 4 | ignorePatterns: ['apps/**', 'packages/**'], 5 | extends: ['@repo/eslint-config/default.cjs'], 6 | } 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Client Information** 11 | - LLM Client: [e.g. Claude Desktop, claude.ai, Cursor, VSCode] 12 | - Client Config: [e.g. claude_desktop_config.json or screenshot of client configuration UI] 13 | - Using MCP Remote?: Yes/No 14 | - MCP Server: [e.g. https://observability.mcp.cloudflare.com, https://docs.mcp.cloudflare.com] 15 | - Prompt: [if applicable, add the prompt used] 16 | 17 | **Describe the bug** 18 | A clear and concise description of what the bug is. Any error logs are helpful. 19 | 20 | **To Reproduce** 21 | Steps to reproduce the behavior: 22 | 1. Connect to MCP Server... 23 | 2. Provide LLM prompt "..." 24 | 4. See error... 25 | 26 | **Expected behavior** 27 | A clear and concise description of what you expected to happen. 28 | 29 | **Additional context** 30 | Add any other context about the problem here. 31 | -------------------------------------------------------------------------------- /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Setup Node.js Environment' 2 | description: 'Install pnpm, Node.js, and project dependencies' 3 | 4 | inputs: 5 | node-version: 6 | description: 'Node.js version to use' 7 | required: false 8 | default: '22' 9 | 10 | runs: 11 | using: "composite" 12 | steps: 13 | - name: Install pnpm 14 | # note: version is inferred from the packageManager field in package.json 15 | uses: pnpm/action-setup@v4 16 | 17 | - name: Use Node.js 18 | uses: actions/setup-node@v4 19 | with: 20 | node-version: ${{ inputs.node-version }} 21 | cache: 'pnpm' 22 | 23 | - name: Install dependencies 24 | shell: bash 25 | run: pnpm install --frozen-lockfile --child-concurrency=10 26 | -------------------------------------------------------------------------------- /.github/workflows/branches.yml: -------------------------------------------------------------------------------- 1 | name: Branches 2 | on: 3 | push: 4 | branches-ignore: ['main'] 5 | 6 | env: 7 | FORCE_COLOR: 1 8 | 9 | jobs: 10 | test: 11 | name: Test & Check 12 | runs-on: ubuntu-24.04 13 | permissions: 14 | contents: read 15 | timeout-minutes: 10 16 | strategy: 17 | matrix: 18 | node-version: [20, 22] 19 | steps: 20 | - uses: actions/checkout@v4 21 | - uses: ./.github/actions/setup 22 | with: 23 | node-version: ${{ matrix.node-version }} 24 | 25 | - name: Syncpack lint 26 | run: pnpm check:deps 27 | - name: Run linter 28 | run: pnpm check:turbo 29 | - name: Run linter (formatting) 30 | run: pnpm check:format 31 | - name: Run tests 32 | run: pnpm test 33 | 34 | build-workers: 35 | name: Build Workers 36 | runs-on: ubuntu-24.04 37 | permissions: 38 | contents: read 39 | timeout-minutes: 10 40 | steps: 41 | - uses: actions/checkout@v4 42 | - uses: ./.github/actions/setup 43 | 44 | - name: Build Workers 45 | run: pnpm turbo deploy -- -e staging --dry-run -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Main 2 | 3 | on: 4 | push: 5 | branches: ['main'] 6 | 7 | env: 8 | FORCE_COLOR: 1 9 | 10 | jobs: 11 | deploy-staging: 12 | name: Deploy (staging) 13 | runs-on: ubuntu-24.04 14 | permissions: 15 | contents: read 16 | timeout-minutes: 10 17 | concurrency: ${{ github.workflow }}-deploy-staging 18 | steps: 19 | - name: Checkout Repo 20 | uses: actions/checkout@v4 21 | - uses: ./.github/actions/setup 22 | 23 | # Run tests & checks before deploying 24 | - name: Syncpack lint 25 | run: pnpm check:deps 26 | - name: Run linter 27 | run: pnpm check:turbo 28 | - name: Run linter (formatting) 29 | run: pnpm check:format 30 | - name: Run tests 31 | run: pnpm test 32 | 33 | - name: Deploy Workers (staging) 34 | run: pnpm turbo deploy -- -e staging 35 | env: 36 | CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} 37 | CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | # Wrangler 3 | .wrangler 4 | .dev.vars 5 | 6 | # Astro generated types 7 | .astro/ 8 | 9 | # Dependencies 10 | node_modules 11 | .pnp 12 | .pnp.js 13 | 14 | .eslintcache 15 | 16 | # Local env files 17 | .env 18 | .env.local 19 | .env.development.local 20 | .env.test.local 21 | .env.production.local 22 | .secret 23 | *.env 24 | 25 | # Testing 26 | coverage 27 | 28 | # Turbo 29 | .turbo 30 | 31 | # Vercel 32 | .vercel 33 | 34 | # Build Outputs 35 | .next/ 36 | out/ 37 | dist 38 | dist2 39 | 40 | # Debug 41 | npm-debug.log* 42 | yarn-debug.log* 43 | yarn-error.log* 44 | 45 | # Misc 46 | .DS_Store 47 | *.pem 48 | .sentryclirc.lock/ 49 | tmp.json 50 | tmp.ts 51 | .idea 52 | 53 | apps/sandbox-container/workdir 54 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | auto-install-peers=true 2 | public-hoist-pattern[]=*eslint* 3 | public-hoist-pattern[]=*prettier* 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .changeset 2 | .github/ 3 | pnpm-lock.yaml 4 | vitest.config.ts.timestamp* 5 | vite.config.ts.timestamp* 6 | worker-configuration.d.ts 7 | **/dist/** 8 | packages/tools/src/test/fixtures/changesets/invalid-json/*.json 9 | -------------------------------------------------------------------------------- /.prettierrc.cjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | const codeImports = [ 4 | // Groups 5 | '', 6 | '', 7 | '', 8 | '^(@repo)(/.*)$', // Workspace imports 9 | '', 10 | // Local (relative) imports 11 | '^[.]{2}$', // .. 12 | '^[.]{2}/', // ../ 13 | '^[.]/(?!index)', // ./foo (but not ./index) 14 | '^[.]$', // . 15 | '^[.]/index$', // ./index 16 | '', 17 | ] 18 | 19 | // Type imports are ordered the same way, but without separators. 20 | // We also need a catch-all here to prevent prettier from failing. 21 | const typeImports = [''].concat( 22 | codeImports.filter((i) => i !== '').map((i) => `${i}`) 23 | ) 24 | 25 | /** @type {import("prettier").Config} */ 26 | const config = { 27 | trailingComma: 'es5', 28 | tabWidth: 2, 29 | useTabs: true, 30 | semi: false, 31 | singleQuote: true, 32 | printWidth: 100, 33 | plugins: ['@ianvs/prettier-plugin-sort-imports'], 34 | importOrder: [...codeImports, ...typeImports], 35 | importOrderTypeScriptVersion: '5.5.4', 36 | overrides: [ 37 | { 38 | files: '*.mdx', 39 | options: { 40 | parser: 'mdx', 41 | }, 42 | }, 43 | { 44 | files: ['*.jsonc', '*.code-workspace'], 45 | options: { 46 | trailingComma: 'none', 47 | }, 48 | }, 49 | ], 50 | } 51 | 52 | module.exports = config 53 | -------------------------------------------------------------------------------- /.syncpackrc.cjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | /** @type {import("syncpack").RcFile} */ 3 | const config = { 4 | indent: '\t', 5 | lintFormatting: false, // handled by prettier 6 | versionGroups: [ 7 | { 8 | label: 'local packages', 9 | packages: ['**'], 10 | dependencies: ['@repo/*'], 11 | dependencyTypes: ['!local'], // Exclude the local package itself 12 | pinVersion: 'workspace:*', 13 | }, 14 | { 15 | label: 'Sentry types that are compatible with toucan-js', 16 | dependencies: ['@sentry/types', '@sentry/tracing'], 17 | pinVersion: '8.9.2', 18 | }, 19 | { 20 | label: 'toucan-js that is compatible with pinned sentry types', 21 | dependencies: ['toucan-js'], 22 | pinVersion: '4.1.1', 23 | }, 24 | { 25 | label: 'pin vitest compatible with @cloudflare/vitest-pool-workers', 26 | dependencies: ['vitest', '@vitest/ui'], 27 | pinVersion: '3.0.9', 28 | }, 29 | { 30 | label: 'pin typescript for eslint', 31 | dependencies: ['typescript'], 32 | pinVersion: '5.5.4', 33 | }, 34 | { 35 | label: `pin eslint and all it's plugins for eslint v8`, 36 | dependencies: [ 37 | 'eslint', 38 | '@types/eslint', 39 | 'eslint-config-prettier', 40 | 'eslint-plugin-react-hooks', 41 | 'eslint-plugin-unused-imports', 42 | '@typescript-eslint/eslint-plugin', 43 | '@typescript-eslint/parser', 44 | ], 45 | // snapTo removes it from syncpack update list, which is the main goal 46 | snapTo: ['@repo/eslint-config'], 47 | }, 48 | { 49 | label: 'use zod v4 in packages/tools', 50 | dependencies: ['zod'], 51 | pinVersion: '4.0.0-beta.20250505T195954', 52 | packages: ['@repo/tools'], 53 | }, 54 | ], 55 | semverGroups: [ 56 | { 57 | label: 'pin all deps', 58 | range: '', 59 | dependencies: ['**'], 60 | packages: ['**'], 61 | }, 62 | ], 63 | } 64 | 65 | module.exports = config 66 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"], 7 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 8 | "unwantedRecommendations": [] 9 | } 10 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Wrangler", 5 | "type": "node", 6 | "request": "attach", 7 | "port": 9229, 8 | "cwd": "/", 9 | "resolveSourceMapLocations": null, 10 | "attachExistingChildren": false, 11 | "autoAttachChildProcesses": false, 12 | "sourceMaps": true // works with or without this line 13 | }, 14 | { 15 | "type": "node", 16 | "request": "launch", 17 | "name": "Open inspector with Vitest", 18 | "runtimeExecutable": "npm", 19 | "runtimeArgs": ["run", "eval:dev"], 20 | "console": "integratedTerminal", 21 | "cwd": "${workspaceFolder}/apps/workers-bindings" 22 | }, 23 | { 24 | "name": "Attach to Workers Runtime", 25 | "type": "node", 26 | "request": "attach", 27 | "port": 9229, 28 | "cwd": "/", 29 | "resolveSourceMapLocations": null, 30 | "attachExistingChildren": false, 31 | "autoAttachChildProcesses": false 32 | } 33 | ], 34 | "compounds": [ 35 | { 36 | "name": "Debug Workers tests", 37 | "configurations": ["Open inspector with Vitest", "Attach to Workers Runtime"], 38 | "stopAll": true 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.detectIndentation": true, 3 | // https://arktype.io/docs/intro/setup#settings 4 | // allow autocomplete for ArkType expressions like "string | num" 5 | "editor.quickSuggestions": { 6 | "strings": "on" 7 | }, 8 | // prioritize ArkType's "type" for autoimports 9 | "typescript.preferences.autoImportSpecifierExcludeRegexes": ["^(node:)?os$"], 10 | "typescript.preferences.autoImportFileExcludePatterns": ["**/vitest/dist/**"], 11 | "typescript.preferences.importModuleSpecifier": "non-relative", 12 | "files.associations": { 13 | "**/packages/tools/bin/*": "shellscript", 14 | "**/*.css": "tailwindcss", 15 | "turbo.json": "jsonc", 16 | "**/packages/typescript-config/*.json": "jsonc" 17 | }, 18 | "eslint.workingDirectories": [ 19 | { 20 | "mode": "auto" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "changeset:new", 7 | "group": "none", 8 | "label": "changeset: new", 9 | "detail": "Create changeset and commit all changes", 10 | "runOptions": { "instanceLimit": 1 }, 11 | "presentation": { 12 | "reveal": "always", 13 | "focus": true, 14 | "panel": "new", 15 | "close": true 16 | } 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Developing 2 | 3 | We welcome contributions to all of our MCP servers! Here's a quick run down on how to get started. 4 | 5 | ## Architecture 6 | 7 | This monorepo has two top-level directories: `/apps` and `/packages`. 8 | 9 | - **/apps**: Containing directories for each server. Within each server, you'll find a `CONTRIBUTING.md` with any special instructions on how to get set up: 10 | - [apps/workers-observability](apps/workers-observability) 11 | - [apps/workers-bindings](apps/workers-bindings) 12 | - [apps/radar](apps/radar) 13 | - [apps/cloudflare-one-casb](apps/cloudflare-one-casb) 14 | - **/packages**: Containing shared packages used across our various apps. 15 | - packages/eslint-config: Eslint config used by all apps and packages. 16 | - packages/typescript-config: tsconfig used by all apps and packages. 17 | - packages/mcp-common: Shared common tools and scripts to help manage this repo. 18 | 19 | We use [TurboRepo](https://turbo.build/) and [pnpm](https://pnpm.io/) to manage this repository. TurboRepo manages the monorepo by ensuring commands are run across all apps. 20 | 21 | ## Getting Started 22 | 23 | This section will guide you through setting up your developer environment and running tests. 24 | 25 | ### Installation 26 | 27 | Install dependencies: 28 | 29 | ```bash 30 | pnpm install 31 | ``` 32 | 33 | ### Testing 34 | 35 | The project uses Vitest as the testing framework with [fetchMock](https://developers.cloudflare.com/workers/testing/vitest-integration/test-apis/) for API mocking. 36 | 37 | #### Running Tests 38 | 39 | To run all tests: 40 | 41 | ```bash 42 | pnpm test 43 | ``` 44 | 45 | To run a specific test file: 46 | 47 | ```bash 48 | pnpm test -- tests/tools/queues.test.ts 49 | ``` 50 | 51 | To run tests in watch mode (useful during development): 52 | 53 | ```bash 54 | pnpm test:watch 55 | ``` 56 | -------------------------------------------------------------------------------- /apps/ai-gateway/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | DEV_DISABLE_OAUTH= 4 | DEV_CLOUDFLARE_API_TOKEN= 5 | DEV_CLOUDFLARE_EMAIL= 6 | -------------------------------------------------------------------------------- /apps/ai-gateway/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/ai-gateway/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # cloudflare-ai-gateway-mcp-server 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | - @repo/mcp-common@0.19.1 11 | 12 | ## 0.1.3 13 | 14 | ### Patch Changes 15 | 16 | - cc6d41f: Update agents deps & modelcontextprotocol 17 | - Updated dependencies [1833c6d] 18 | - Updated dependencies [cc6d41f] 19 | - @repo/mcp-common@0.19.0 20 | - @repo/mcp-observability@0.32.1 21 | 22 | ## 0.1.2 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [f885d07] 27 | - @repo/mcp-common@0.18.0 28 | 29 | ## 0.1.1 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [83e2d19] 34 | - @repo/mcp-common@0.17.1 35 | 36 | ## 0.1.0 37 | 38 | ### Minor Changes 39 | 40 | - 6cf52a6: Support AOT tokens 41 | 42 | ### Patch Changes 43 | 44 | - 0fc4439: Update agents and modelcontext dependencies 45 | - Updated dependencies [6cf52a6] 46 | - Updated dependencies [0fc4439] 47 | - @repo/mcp-observability@0.32.0 48 | - @repo/mcp-common@0.17.0 49 | 50 | ## 0.0.4 51 | 52 | ### Patch Changes 53 | 54 | - 3677a18: Remove extraneous log 55 | - Updated dependencies [3677a18] 56 | - @repo/mcp-common@0.16.3 57 | 58 | ## 0.0.3 59 | 60 | ### Patch Changes 61 | 62 | - 86c2e4f: Add API token passthrough auth 63 | - Updated dependencies [86c2e4f] 64 | - @repo/mcp-common@0.16.2 65 | 66 | ## 0.0.2 67 | 68 | ### Patch Changes 69 | 70 | - cf3771b: chore: add suffixes to common files in apps and packages 71 | 72 | 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. 73 | 74 | - Updated dependencies [cf3771b] 75 | - @repo/mcp-common@0.16.1 76 | - @repo/mcp-observability@0.31.1 77 | -------------------------------------------------------------------------------- /apps/ai-gateway/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | If you'd like to iterate and test your MCP server, you can do so in local development. 4 | 5 | ## Local Development 6 | 7 | 1. Create a `.dev.vars` file in your project root: 8 | 9 | If you're a Cloudflare employee: 10 | 11 | ``` 12 | CLOUDFLARE_CLIENT_ID=your_development_cloudflare_client_id 13 | CLOUDFLARE_CLIENT_SECRET=your_development_cloudflare_client_secret 14 | ``` 15 | 16 | If you're an external contributor, you can provide a development API token: 17 | 18 | ``` 19 | DEV_DISABLE_OAUTH=true 20 | # This is your global api token 21 | DEV_CLOUDFLARE_API_TOKEN=your_development_api_token 22 | ``` 23 | 24 | 2. Start the local development server: 25 | 26 | ```bash 27 | npx wrangler dev 28 | ``` 29 | 30 | 3. To test locally, open Inspector, and connect to `http://localhost:8976/sse`. 31 | Once you follow the prompts, you'll be able to "List Tools". You can also connect with any MCP client. 32 | 33 | ## Deploying the Worker ( Cloudflare employees only ) 34 | 35 | Set secrets via Wrangler: 36 | 37 | ```bash 38 | npx wrangler secret put CLOUDFLARE_CLIENT_ID -e 39 | npx wrangler secret put CLOUDFLARE_CLIENT_SECRET -e 40 | ``` 41 | 42 | ## Set up a KV namespace 43 | 44 | Create the KV namespace: 45 | 46 | ```bash 47 | npx wrangler kv namespace create "OAUTH_KV" 48 | ``` 49 | 50 | Then, update the Wrangler file with the generated KV namespace ID. 51 | 52 | ## Deploy & Test 53 | 54 | Deploy the MCP server to make it available on your workers.dev domain: 55 | 56 | ```bash 57 | npx wrangler deploy -e 58 | ``` 59 | 60 | Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector): 61 | 62 | ```bash 63 | npx @modelcontextprotocol/inspector@latest 64 | ``` 65 | -------------------------------------------------------------------------------- /apps/ai-gateway/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloudflare-ai-gateway-mcp-server", 3 | "version": "0.1.4", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "run-wrangler-deploy", 9 | "dev": "wrangler dev", 10 | "start": "wrangler dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-common": "workspace:*", 19 | "@repo/mcp-observability": "workspace:*", 20 | "agents": "0.0.100", 21 | "cloudflare": "4.2.0", 22 | "hono": "4.7.6", 23 | "zod": "3.24.2" 24 | }, 25 | "devDependencies": { 26 | "@cloudflare/vitest-pool-workers": "0.8.14", 27 | "@types/node": "22.14.1", 28 | "prettier": "3.5.3", 29 | "typescript": "5.5.4", 30 | "vitest": "3.0.9", 31 | "wrangler": "4.10.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /apps/ai-gateway/src/ai-gateway.context.ts: -------------------------------------------------------------------------------- 1 | import type { UserDetails } from '@repo/mcp-common/src/durable-objects/user_details.do' 2 | import type { AIGatewayMCP } from './ai-gateway.app' 3 | 4 | export interface Env { 5 | OAUTH_KV: KVNamespace 6 | ENVIRONMENT: 'development' | 'staging' | 'production' 7 | MCP_SERVER_NAME: string 8 | MCP_SERVER_VERSION: string 9 | CLOUDFLARE_CLIENT_ID: string 10 | CLOUDFLARE_CLIENT_SECRET: string 11 | MCP_OBJECT: DurableObjectNamespace 12 | USER_DETAILS: DurableObjectNamespace 13 | MCP_METRICS: AnalyticsEngineDataset 14 | DEV_DISABLE_OAUTH: string 15 | DEV_CLOUDFLARE_API_TOKEN: string 16 | DEV_CLOUDFLARE_EMAIL: string 17 | } 18 | -------------------------------------------------------------------------------- /apps/ai-gateway/src/types.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const GatewayIdParam = z.string().describe('The gateway ID.') 4 | export const LogIdParam = z.string() 5 | export const pageParam = z.number().int().min(1).optional().default(1) 6 | export const perPageParam = z.number().int().min(1).max(50).optional().default(20) 7 | 8 | export const ListLogsParams = { 9 | gateway_id: GatewayIdParam, 10 | page: pageParam, 11 | per_page: perPageParam, 12 | order_by: z 13 | .enum([ 14 | 'created_at', 15 | 'provider', 16 | 'model', 17 | 'model_type', 18 | 'success', 19 | 'cached', 20 | 'cost', 21 | 'tokens_in', 22 | 'tokens_out', 23 | 'duration', 24 | 'feedback', 25 | ]) 26 | .optional() 27 | .default('created_at'), 28 | order_by_direction: z.enum(['asc', 'desc']).optional().default('desc'), 29 | start_date: z.string().datetime().optional(), 30 | end_date: z.string().datetime().optional(), 31 | feedback: z.union([z.literal(-1), z.literal(0), z.literal(1)]).optional(), 32 | success: z.boolean().optional(), 33 | cached: z.boolean().optional(), 34 | model: z.string().toLowerCase().optional(), 35 | provider: z.string().toLowerCase().optional(), 36 | } 37 | -------------------------------------------------------------------------------- /apps/ai-gateway/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.ts", "./types.d.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/ai-gateway/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/ai-gateway/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/ai-gateway.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /apps/auditlogs/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | DEV_DISABLE_OAUTH= 4 | DEV_CLOUDFLARE_API_TOKEN= 5 | DEV_CLOUDFLARE_EMAIL= -------------------------------------------------------------------------------- /apps/auditlogs/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/auditlogs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # auditlogs 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | - @repo/mcp-common@0.19.1 11 | 12 | ## 0.1.3 13 | 14 | ### Patch Changes 15 | 16 | - cc6d41f: Update agents deps & modelcontextprotocol 17 | - Updated dependencies [1833c6d] 18 | - Updated dependencies [cc6d41f] 19 | - @repo/mcp-common@0.19.0 20 | - @repo/mcp-observability@0.32.1 21 | 22 | ## 0.1.2 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [f885d07] 27 | - @repo/mcp-common@0.18.0 28 | 29 | ## 0.1.1 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [83e2d19] 34 | - @repo/mcp-common@0.17.1 35 | 36 | ## 0.1.0 37 | 38 | ### Minor Changes 39 | 40 | - 6cf52a6: Support AOT tokens 41 | 42 | ### Patch Changes 43 | 44 | - 0fc4439: Update agents and modelcontext dependencies 45 | - Updated dependencies [6cf52a6] 46 | - Updated dependencies [0fc4439] 47 | - @repo/mcp-observability@0.32.0 48 | - @repo/mcp-common@0.17.0 49 | 50 | ## 0.0.4 51 | 52 | ### Patch Changes 53 | 54 | - 3677a18: Remove extraneous log 55 | - Updated dependencies [3677a18] 56 | - @repo/mcp-common@0.16.3 57 | 58 | ## 0.0.3 59 | 60 | ### Patch Changes 61 | 62 | - 86c2e4f: Add API token passthrough auth 63 | - Updated dependencies [86c2e4f] 64 | - @repo/mcp-common@0.16.2 65 | 66 | ## 0.0.2 67 | 68 | ### Patch Changes 69 | 70 | - cf3771b: chore: add suffixes to common files in apps and packages 71 | 72 | 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. 73 | 74 | - Updated dependencies [cf3771b] 75 | - @repo/mcp-common@0.16.1 76 | - @repo/mcp-observability@0.31.1 77 | -------------------------------------------------------------------------------- /apps/auditlogs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "auditlogs", 3 | "version": "0.1.4", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "wrangler deploy", 9 | "dev": "wrangler dev", 10 | "start": "wrangler dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-common": "workspace:*", 19 | "@repo/mcp-observability": "workspace:*", 20 | "agents": "0.0.100", 21 | "cloudflare": "4.2.0", 22 | "hono": "4.7.6", 23 | "zod": "3.24.2" 24 | }, 25 | "devDependencies": { 26 | "@cloudflare/vitest-pool-workers": "0.8.14", 27 | "@types/node": "22.14.1", 28 | "prettier": "3.5.3", 29 | "typescript": "5.5.4", 30 | "vitest": "3.0.9", 31 | "wrangler": "4.10.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /apps/auditlogs/src/auditlogs.context.ts: -------------------------------------------------------------------------------- 1 | import type { UserDetails } from '@repo/mcp-common/src/durable-objects/user_details.do' 2 | import type { AuditlogMCP } from './auditlogs.app' 3 | 4 | export interface Env { 5 | OAUTH_KV: KVNamespace 6 | ENVIRONMENT: 'development' | 'staging' | 'production' 7 | MCP_SERVER_NAME: string 8 | MCP_SERVER_VERSION: string 9 | CLOUDFLARE_ACCESS_TOKEN: string 10 | CLOUDFLARE_CLIENT_ID: string 11 | CLOUDFLARE_CLIENT_SECRET: string 12 | MCP_OBJECT: DurableObjectNamespace 13 | USER_DETAILS: DurableObjectNamespace 14 | MCP_METRICS: AnalyticsEngineDataset 15 | DEV_DISABLE_OAUTH: string 16 | DEV_CLOUDFLARE_API_TOKEN: string 17 | DEV_CLOUDFLARE_EMAIL: string 18 | } 19 | -------------------------------------------------------------------------------- /apps/auditlogs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "worker-configuration.d.ts", "./vitest.config.ts", "./types.d.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/auditlogs/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/auditlogs/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/auditlogs.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /apps/autorag/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | DEV_DISABLE_OAUTH= 4 | DEV_CLOUDFLARE_API_TOKEN= 5 | DEV_CLOUDFLARE_EMAIL= 6 | -------------------------------------------------------------------------------- /apps/autorag/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/autorag/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # cloudflare-autorag-mcp-server 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | - @repo/mcp-common@0.19.1 11 | 12 | ## 0.1.3 13 | 14 | ### Patch Changes 15 | 16 | - cc6d41f: Update agents deps & modelcontextprotocol 17 | - Updated dependencies [1833c6d] 18 | - Updated dependencies [cc6d41f] 19 | - @repo/mcp-common@0.19.0 20 | - @repo/mcp-observability@0.32.1 21 | 22 | ## 0.1.2 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [f885d07] 27 | - @repo/mcp-common@0.18.0 28 | 29 | ## 0.1.1 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [83e2d19] 34 | - @repo/mcp-common@0.17.1 35 | 36 | ## 0.1.0 37 | 38 | ### Minor Changes 39 | 40 | - 6cf52a6: Support AOT tokens 41 | 42 | ### Patch Changes 43 | 44 | - 0fc4439: Update agents and modelcontext dependencies 45 | - Updated dependencies [6cf52a6] 46 | - Updated dependencies [0fc4439] 47 | - @repo/mcp-observability@0.32.0 48 | - @repo/mcp-common@0.17.0 49 | 50 | ## 0.0.4 51 | 52 | ### Patch Changes 53 | 54 | - 3677a18: Remove extraneous log 55 | - Updated dependencies [3677a18] 56 | - @repo/mcp-common@0.16.3 57 | 58 | ## 0.0.3 59 | 60 | ### Patch Changes 61 | 62 | - 86c2e4f: Add API token passthrough auth 63 | - Updated dependencies [86c2e4f] 64 | - @repo/mcp-common@0.16.2 65 | 66 | ## 0.0.2 67 | 68 | ### Patch Changes 69 | 70 | - cf3771b: chore: add suffixes to common files in apps and packages 71 | 72 | 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. 73 | 74 | - Updated dependencies [cf3771b] 75 | - @repo/mcp-common@0.16.1 76 | - @repo/mcp-observability@0.31.1 77 | -------------------------------------------------------------------------------- /apps/autorag/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | If you'd like to iterate and test your MCP server, you can do so in local development. 4 | 5 | ## Local Development 6 | 7 | 1. Create a `.dev.vars` file in your project root: 8 | 9 | If you're a Cloudflare employee: 10 | 11 | ``` 12 | CLOUDFLARE_CLIENT_ID=your_development_cloudflare_client_id 13 | CLOUDFLARE_CLIENT_SECRET=your_development_cloudflare_client_secret 14 | ``` 15 | 16 | If you're an external contributor, you can provide a development API token: 17 | 18 | ``` 19 | DEV_DISABLE_OAUTH=true 20 | # This is your global api token 21 | DEV_CLOUDFLARE_API_TOKEN=your_development_api_token 22 | ``` 23 | 24 | 2. Start the local development server: 25 | 26 | ```bash 27 | npx wrangler dev 28 | ``` 29 | 30 | 3. To test locally, open Inspector, and connect to `http://localhost:8976/sse`. 31 | Once you follow the prompts, you'll be able to "List Tools". You can also connect with any MCP client. 32 | 33 | ## Deploying the Worker ( Cloudflare employees only ) 34 | 35 | Set secrets via Wrangler: 36 | 37 | ```bash 38 | npx wrangler secret put CLOUDFLARE_CLIENT_ID -e 39 | npx wrangler secret put CLOUDFLARE_CLIENT_SECRET -e 40 | npx wrangler secret put URL_SCANNER_API_TOKEN -e 41 | ``` 42 | 43 | ## Set up a KV namespace 44 | 45 | Create the KV namespace: 46 | 47 | ```bash 48 | npx wrangler kv namespace create "OAUTH_KV" 49 | ``` 50 | 51 | Then, update the Wrangler file with the generated KV namespace ID. 52 | 53 | ## Deploy & Test 54 | 55 | Deploy the MCP server to make it available on your workers.dev domain: 56 | 57 | ```bash 58 | npx wrangler deploy -e 59 | ``` 60 | 61 | Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector): 62 | 63 | ```bash 64 | npx @modelcontextprotocol/inspector@latest 65 | ``` 66 | -------------------------------------------------------------------------------- /apps/autorag/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloudflare-autorag-mcp-server", 3 | "version": "0.1.4", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "run-wrangler-deploy", 9 | "dev": "wrangler dev", 10 | "start": "wrangler dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-common": "workspace:*", 19 | "@repo/mcp-observability": "workspace:*", 20 | "agents": "0.0.100", 21 | "cloudflare": "4.2.0", 22 | "hono": "4.7.6", 23 | "zod": "3.24.2" 24 | }, 25 | "devDependencies": { 26 | "@cloudflare/vitest-pool-workers": "0.8.14", 27 | "@types/node": "22.14.1", 28 | "prettier": "3.5.3", 29 | "typescript": "5.5.4", 30 | "vitest": "3.0.9", 31 | "wrangler": "4.10.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /apps/autorag/src/autorag.context.ts: -------------------------------------------------------------------------------- 1 | import type { UserDetails } from '@repo/mcp-common/src/durable-objects/user_details.do' 2 | import type { AutoRAGMCP } from './autorag.app' 3 | 4 | export interface Env { 5 | OAUTH_KV: KVNamespace 6 | ENVIRONMENT: 'development' | 'staging' | 'production' 7 | MCP_SERVER_NAME: string 8 | MCP_SERVER_VERSION: string 9 | CLOUDFLARE_CLIENT_ID: string 10 | CLOUDFLARE_CLIENT_SECRET: string 11 | MCP_OBJECT: DurableObjectNamespace 12 | USER_DETAILS: DurableObjectNamespace 13 | MCP_METRICS: AnalyticsEngineDataset 14 | DEV_DISABLE_OAUTH: string 15 | DEV_CLOUDFLARE_API_TOKEN: string 16 | DEV_CLOUDFLARE_EMAIL: string 17 | } 18 | -------------------------------------------------------------------------------- /apps/autorag/src/types.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const pageParam = z.number().int().min(1).optional().default(1) 4 | export const perPageParam = z.number().int().min(1).max(50).optional().default(20) 5 | -------------------------------------------------------------------------------- /apps/autorag/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.ts", "./types.d.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/autorag/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/autorag/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/autorag.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /apps/browser-rendering/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | DEV_DISABLE_OAUTH= 4 | DEV_CLOUDFLARE_API_TOKEN= 5 | DEV_CLOUDFLARE_EMAIL= 6 | -------------------------------------------------------------------------------- /apps/browser-rendering/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/browser-rendering/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # cloudflare-browser-mcp-server 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | - @repo/mcp-common@0.19.1 11 | 12 | ## 0.1.3 13 | 14 | ### Patch Changes 15 | 16 | - cc6d41f: Update agents deps & modelcontextprotocol 17 | - Updated dependencies [1833c6d] 18 | - Updated dependencies [cc6d41f] 19 | - @repo/mcp-common@0.19.0 20 | - @repo/mcp-observability@0.32.1 21 | 22 | ## 0.1.2 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [f885d07] 27 | - @repo/mcp-common@0.18.0 28 | 29 | ## 0.1.1 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [83e2d19] 34 | - @repo/mcp-common@0.17.1 35 | 36 | ## 0.1.0 37 | 38 | ### Minor Changes 39 | 40 | - 6cf52a6: Support AOT tokens 41 | 42 | ### Patch Changes 43 | 44 | - 0fc4439: Update agents and modelcontext dependencies 45 | - Updated dependencies [6cf52a6] 46 | - Updated dependencies [0fc4439] 47 | - @repo/mcp-observability@0.32.0 48 | - @repo/mcp-common@0.17.0 49 | 50 | ## 0.0.4 51 | 52 | ### Patch Changes 53 | 54 | - 3677a18: Remove extraneous log 55 | - Updated dependencies [3677a18] 56 | - @repo/mcp-common@0.16.3 57 | 58 | ## 0.0.3 59 | 60 | ### Patch Changes 61 | 62 | - 86c2e4f: Add API token passthrough auth 63 | - Updated dependencies [86c2e4f] 64 | - @repo/mcp-common@0.16.2 65 | 66 | ## 0.0.2 67 | 68 | ### Patch Changes 69 | 70 | - cf3771b: chore: add suffixes to common files in apps and packages 71 | 72 | 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. 73 | 74 | - Updated dependencies [cf3771b] 75 | - @repo/mcp-common@0.16.1 76 | - @repo/mcp-observability@0.31.1 77 | -------------------------------------------------------------------------------- /apps/browser-rendering/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | If you'd like to iterate and test your MCP server, you can do so in local development. 4 | 5 | ## Local Development 6 | 7 | 1. Create a `.dev.vars` file in your project root: 8 | 9 | If you're a Cloudflare employee: 10 | 11 | ``` 12 | CLOUDFLARE_CLIENT_ID=your_development_cloudflare_client_id 13 | CLOUDFLARE_CLIENT_SECRET=your_development_cloudflare_client_secret 14 | ``` 15 | 16 | If you're an external contributor, you can provide a development API token: 17 | 18 | ``` 19 | DEV_DISABLE_OAUTH=true 20 | # This is your global api token 21 | DEV_CLOUDFLARE_API_TOKEN=your_development_api_token 22 | ``` 23 | 24 | 2. Start the local development server: 25 | 26 | ```bash 27 | npx wrangler dev 28 | ``` 29 | 30 | 3. To test locally, open Inspector, and connect to `http://localhost:8976/sse`. 31 | Once you follow the prompts, you'll be able to "List Tools". You can also connect with any MCP client. 32 | 33 | ## Deploying the Worker ( Cloudflare employees only ) 34 | 35 | Set secrets via Wrangler: 36 | 37 | ```bash 38 | npx wrangler secret put CLOUDFLARE_CLIENT_ID -e 39 | npx wrangler secret put CLOUDFLARE_CLIENT_SECRET -e 40 | ``` 41 | 42 | ## Set up a KV namespace 43 | 44 | Create the KV namespace: 45 | 46 | ```bash 47 | npx wrangler kv namespace create "OAUTH_KV" 48 | ``` 49 | 50 | Then, update the Wrangler file with the generated KV namespace ID. 51 | 52 | ## Deploy & Test 53 | 54 | Deploy the MCP server to make it available on your workers.dev domain: 55 | 56 | ```bash 57 | npx wrangler deploy -e 58 | ``` 59 | 60 | Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector): 61 | 62 | ```bash 63 | npx @modelcontextprotocol/inspector@latest 64 | ``` 65 | -------------------------------------------------------------------------------- /apps/browser-rendering/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloudflare-browser-mcp-server", 3 | "version": "0.1.4", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "run-wrangler-deploy", 9 | "dev": "wrangler dev", 10 | "start": "wrangler dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-common": "workspace:*", 19 | "@repo/mcp-observability": "workspace:*", 20 | "agents": "0.0.100", 21 | "cloudflare": "4.2.0", 22 | "hono": "4.7.6", 23 | "zod": "3.24.2" 24 | }, 25 | "devDependencies": { 26 | "@cloudflare/vitest-pool-workers": "0.8.14", 27 | "@types/node": "22.14.1", 28 | "prettier": "3.5.3", 29 | "typescript": "5.5.4", 30 | "vitest": "3.0.9", 31 | "wrangler": "4.10.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /apps/browser-rendering/src/browser.context.ts: -------------------------------------------------------------------------------- 1 | import type { UserDetails } from '@repo/mcp-common/src/durable-objects/user_details.do' 2 | import type { BrowserMCP } from './browser.app' 3 | 4 | export interface Env { 5 | OAUTH_KV: KVNamespace 6 | ENVIRONMENT: 'development' | 'staging' | 'production' 7 | MCP_SERVER_NAME: string 8 | MCP_SERVER_VERSION: string 9 | CLOUDFLARE_CLIENT_ID: string 10 | CLOUDFLARE_CLIENT_SECRET: string 11 | MCP_OBJECT: DurableObjectNamespace 12 | USER_DETAILS: DurableObjectNamespace 13 | MCP_METRICS: AnalyticsEngineDataset 14 | DEV_DISABLE_OAUTH: string 15 | DEV_CLOUDFLARE_API_TOKEN: string 16 | DEV_CLOUDFLARE_EMAIL: string 17 | } 18 | -------------------------------------------------------------------------------- /apps/browser-rendering/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.ts", "./types.d.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/browser-rendering/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/browser-rendering/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/browser.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /apps/cloudflare-one-casb/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | DEV_DISABLE_OAUTH= 4 | DEV_CLOUDFLARE_API_TOKEN= 5 | DEV_CLOUDFLARE_EMAIL= -------------------------------------------------------------------------------- /apps/cloudflare-one-casb/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/cloudflare-one-casb/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # cloudflare-casb-mcp-server 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-common@0.19.1 10 | 11 | ## 0.1.3 12 | 13 | ### Patch Changes 14 | 15 | - cc6d41f: Update agents deps & modelcontextprotocol 16 | - Updated dependencies [1833c6d] 17 | - Updated dependencies [cc6d41f] 18 | - @repo/mcp-common@0.19.0 19 | 20 | ## 0.1.2 21 | 22 | ### Patch Changes 23 | 24 | - Updated dependencies [f885d07] 25 | - @repo/mcp-common@0.18.0 26 | 27 | ## 0.1.1 28 | 29 | ### Patch Changes 30 | 31 | - Updated dependencies [83e2d19] 32 | - @repo/mcp-common@0.17.1 33 | 34 | ## 0.1.0 35 | 36 | ### Minor Changes 37 | 38 | - 6cf52a6: Support AOT tokens 39 | 40 | ### Patch Changes 41 | 42 | - 0fc4439: Update agents and modelcontext dependencies 43 | - Updated dependencies [6cf52a6] 44 | - Updated dependencies [0fc4439] 45 | - @repo/mcp-common@0.17.0 46 | 47 | ## 0.0.4 48 | 49 | ### Patch Changes 50 | 51 | - 3677a18: Remove extraneous log 52 | - Updated dependencies [3677a18] 53 | - @repo/mcp-common@0.16.3 54 | 55 | ## 0.0.3 56 | 57 | ### Patch Changes 58 | 59 | - 86c2e4f: Add API token passthrough auth 60 | - Updated dependencies [86c2e4f] 61 | - @repo/mcp-common@0.16.2 62 | 63 | ## 0.0.2 64 | 65 | ### Patch Changes 66 | 67 | - cf3771b: chore: add suffixes to common files in apps and packages 68 | 69 | 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. 70 | 71 | - Updated dependencies [cf3771b] 72 | - @repo/mcp-common@0.16.1 73 | -------------------------------------------------------------------------------- /apps/cloudflare-one-casb/README.md: -------------------------------------------------------------------------------- 1 | # Model Context Protocol (MCP) Server + Cloudflare OAuth 2 | 3 | This is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) server that supports remote MCP connections, with Cloudflare OAuth built-in. 4 | 5 | You should use this as a template to build an MCP server for Cloudflare, provided by Cloudflare at `server-name.mcp.cloudflare.com`. It has a basic set of tools `apps/template-start-here/src/tools/logpush.tools.ts` — you can modify these to do what you need 6 | 7 | ## Getting Started 8 | 9 | - Set secrets via Wrangler 10 | 11 | ```bash 12 | wrangler secret put CLOUDFLARE_CLIENT_ID 13 | wrangler secret put CLOUDFLARE_CLIENT_SECRET 14 | ``` 15 | 16 | #### Set up a KV namespace 17 | 18 | - Create the KV namespace: 19 | `wrangler kv:namespace create "OAUTH_KV"` 20 | - Update the Wrangler file with the KV ID 21 | 22 | #### Deploy & Test 23 | 24 | Deploy the MCP server to make it available on your workers.dev domain 25 | ` wrangler deploy` 26 | 27 | Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector): 28 | 29 | ``` 30 | npx wrangler deploy 31 | ``` 32 | -------------------------------------------------------------------------------- /apps/cloudflare-one-casb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloudflare-casb-mcp-server", 3 | "version": "0.1.4", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "run-wrangler-deploy", 9 | "dev": "wrangler dev", 10 | "start": "wrangler dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-common": "workspace:*", 19 | "agents": "0.0.100", 20 | "cloudflare": "4.2.0", 21 | "hono": "4.7.6", 22 | "zod": "3.24.2" 23 | }, 24 | "devDependencies": { 25 | "@cloudflare/vitest-pool-workers": "0.8.14", 26 | "@types/jsonwebtoken": "9.0.9", 27 | "@types/node": "22.14.1", 28 | "prettier": "3.5.3", 29 | "typescript": "5.5.4", 30 | "vitest": "3.0.9", 31 | "wrangler": "4.10.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /apps/cloudflare-one-casb/src/cf1-casb.context.ts: -------------------------------------------------------------------------------- 1 | import type { CASBMCP, UserDetails } from './cf1-casb.app' 2 | 3 | export interface Env { 4 | ENVIRONMENT: 'development' | 'staging' | 'production' 5 | MCP_SERVER_NAME: string 6 | MCP_SERVER_VERSION: string 7 | MCP_OBJECT: DurableObjectNamespace 8 | MCP_METRICS: AnalyticsEngineDataset 9 | AI: Ai 10 | CLOUDFLARE_CLIENT_ID: string 11 | CLOUDFLARE_CLIENT_SECRET: string 12 | USER_DETAILS: DurableObjectNamespace 13 | DEV_DISABLE_OAUTH: string 14 | DEV_CLOUDFLARE_API_TOKEN: string 15 | DEV_CLOUDFLARE_EMAIL: string 16 | } 17 | -------------------------------------------------------------------------------- /apps/cloudflare-one-casb/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./types.d.ts", "./vitest.config.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/cloudflare-one-casb/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/cloudflare-one-casb/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/cf1-casb.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /apps/demo-day/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/demo-day/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # demo-day 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | - @repo/mcp-common@0.19.1 11 | 12 | ## 0.1.3 13 | 14 | ### Patch Changes 15 | 16 | - cc6d41f: Update agents deps & modelcontextprotocol 17 | - Updated dependencies [1833c6d] 18 | - Updated dependencies [cc6d41f] 19 | - @repo/mcp-common@0.19.0 20 | - @repo/mcp-observability@0.32.1 21 | 22 | ## 0.1.2 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [f885d07] 27 | - @repo/mcp-common@0.18.0 28 | 29 | ## 0.1.1 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [83e2d19] 34 | - @repo/mcp-common@0.17.1 35 | 36 | ## 0.1.0 37 | 38 | ### Minor Changes 39 | 40 | - 6cf52a6: Support AOT tokens 41 | 42 | ### Patch Changes 43 | 44 | - 0fc4439: Update agents and modelcontext dependencies 45 | - Updated dependencies [6cf52a6] 46 | - Updated dependencies [0fc4439] 47 | - @repo/mcp-observability@0.32.0 48 | - @repo/mcp-common@0.17.0 49 | 50 | ## 0.0.4 51 | 52 | ### Patch Changes 53 | 54 | - 3677a18: Remove extraneous log 55 | - Updated dependencies [3677a18] 56 | - @repo/mcp-common@0.16.3 57 | 58 | ## 0.0.3 59 | 60 | ### Patch Changes 61 | 62 | - Updated dependencies [86c2e4f] 63 | - @repo/mcp-common@0.16.2 64 | 65 | ## 0.0.2 66 | 67 | ### Patch Changes 68 | 69 | - cf3771b: chore: add suffixes to common files in apps and packages 70 | 71 | 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. 72 | 73 | - Updated dependencies [cf3771b] 74 | - @repo/mcp-common@0.16.1 75 | - @repo/mcp-observability@0.31.1 76 | -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/anthropic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/asana.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/atlassian.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/canva.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/dina.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/mcp-server-cloudflare/main/apps/demo-day/frontend/public/dina.jpg -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/mcp-server-cloudflare/main/apps/demo-day/frontend/public/favicon-16x16.png -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/mcp-server-cloudflare/main/apps/demo-day/frontend/public/favicon-32x32.png -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/mcp-server-cloudflare/main/apps/demo-day/frontend/public/favicon.ico -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/mcp-server-cloudflare/main/apps/demo-day/frontend/public/favicon.png -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/linear.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/matt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/mcp-server-cloudflare/main/apps/demo-day/frontend/public/matt.jpg -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/mcpog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/mcp-server-cloudflare/main/apps/demo-day/frontend/public/mcpog.png -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/more.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/paypal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/pete.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/mcp-server-cloudflare/main/apps/demo-day/frontend/public/pete.jpeg -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/sentry.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/special_guest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/mcp-server-cloudflare/main/apps/demo-day/frontend/public/special_guest.png -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/square.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/sunil.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/mcp-server-cloudflare/main/apps/demo-day/frontend/public/sunil.jpg -------------------------------------------------------------------------------- /apps/demo-day/frontend/public/webflow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/demo-day/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-day", 3 | "version": "0.1.4", 4 | "private": true, 5 | "scripts": { 6 | "check:types": "run-tsc", 7 | "deploy": "run-wrangler-deploy", 8 | "dev": "wrangler dev", 9 | "start": "wrangler dev", 10 | "types": "wrangler types --include-env=false", 11 | "test": "vitest run" 12 | }, 13 | "dependencies": { 14 | "@modelcontextprotocol/sdk": "1.13.3", 15 | "@repo/mcp-common": "workspace:*", 16 | "@repo/mcp-observability": "workspace:*", 17 | "agents": "0.0.100", 18 | "zod": "3.24.2" 19 | }, 20 | "devDependencies": { 21 | "@cloudflare/vitest-pool-workers": "0.8.14", 22 | "@types/node": "22.14.1", 23 | "prettier": "3.5.3", 24 | "typescript": "5.5.4", 25 | "vitest": "3.0.9", 26 | "wrangler": "4.10.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /apps/demo-day/src/demo-day.app.ts: -------------------------------------------------------------------------------- 1 | import { McpAgent } from 'agents/mcp' 2 | 3 | import { getEnv } from '@repo/mcp-common/src/env' 4 | import { CloudflareMCPServer } from '@repo/mcp-common/src/server' 5 | 6 | // The demo day MCP server isn't stateful, so we don't have state/props 7 | export type Props = never 8 | 9 | export type State = never 10 | 11 | export type Env = { 12 | ENVIRONMENT: 'development' | 'staging' | 'production' 13 | AUTORAG_NAME: 'cloudflare-docs-autorag' 14 | MCP_SERVER_NAME: 'PLACEHOLDER' 15 | MCP_SERVER_VERSION: 'PLACEHOLDER' 16 | MCP_OBJECT: DurableObjectNamespace 17 | MCP_METRICS: AnalyticsEngineDataset 18 | ASSETS: Fetcher 19 | } 20 | 21 | const env = getEnv() 22 | 23 | export class CloudflareDemoDayMCP extends McpAgent { 24 | server = new CloudflareMCPServer({ 25 | wae: env.MCP_METRICS, 26 | serverInfo: { 27 | name: env.MCP_SERVER_NAME, 28 | version: env.MCP_SERVER_VERSION, 29 | }, 30 | }) 31 | 32 | constructor( 33 | public ctx: DurableObjectState, 34 | public env: Env 35 | ) { 36 | super(ctx, env) 37 | } 38 | 39 | async init() { 40 | this.server.tool( 41 | 'mcp_demo_day_info', 42 | "Get information about Cloudflare's MCP Demo Day. Use this tool if the user asks about Cloudflare's MCP demo day", 43 | async () => { 44 | const res = await this.env.ASSETS.fetch('https://assets.local/index.html') 45 | return { 46 | content: [ 47 | { 48 | type: 'resource', 49 | resource: { 50 | uri: 'https://demo-day.mcp.cloudflare.com', 51 | mimeType: 'text/html', 52 | text: await res.text(), 53 | }, 54 | }, 55 | { 56 | type: 'text', 57 | 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.", 58 | }, 59 | ], 60 | } 61 | } 62 | ) 63 | } 64 | } 65 | 66 | export default CloudflareDemoDayMCP.mount('/sse') 67 | -------------------------------------------------------------------------------- /apps/demo-day/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["src/demo-day.app.ts"], 4 | "compilerOptions": { 5 | "types": ["@types/node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/demo-day/wrangler.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "main": "src/demo-day.app.ts", 4 | "compatibility_date": "2025-03-10", 5 | "compatibility_flags": ["nodejs_compat"], 6 | "account_id": "6702657b6aa048cf3081ff3ff3c9c52f", 7 | "routes": [{ "pattern": "demo-day.mcp.cloudflare.com", "custom_domain": true }], 8 | "name": "mcp-cloudflare-demo-day", 9 | "migrations": [ 10 | { 11 | "new_sqlite_classes": ["CloudflareDemoDayMCP"], 12 | "tag": "v1" 13 | } 14 | ], 15 | "observability": { 16 | "enabled": true 17 | }, 18 | "durable_objects": { 19 | "bindings": [ 20 | { 21 | "class_name": "CloudflareDemoDayMCP", 22 | "name": "MCP_OBJECT" 23 | } 24 | ] 25 | }, 26 | "assets": { 27 | "directory": "./frontend", 28 | "binding": "ASSETS" 29 | }, 30 | "vars": { 31 | "ENVIRONMENT": "development", 32 | "MCP_SERVER_NAME": "PLACEHOLDER", 33 | "MCP_SERVER_VERSION": "PLACEHOLDER" 34 | }, 35 | "dev": { 36 | "port": 8976 37 | }, 38 | "workers_dev": false, 39 | "preview_urls": false, 40 | "analytics_engine_datasets": [ 41 | { 42 | "binding": "MCP_METRICS", 43 | "dataset": "mcp-metrics-production" 44 | } 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /apps/dex-analysis/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | DEV_DISABLE_OAUTH= 4 | DEV_CLOUDFLARE_API_TOKEN= 5 | DEV_CLOUDFLARE_EMAIL= -------------------------------------------------------------------------------- /apps/dex-analysis/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/dex-analysis/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # dex-analysis 2 | 3 | ## 0.1.6 4 | 5 | ### Patch Changes 6 | 7 | - d672471: dex-analysis: add WARP diag analysis tools and reader D.O. 8 | 9 | ## 0.1.5 10 | 11 | ### Patch Changes 12 | 13 | - 016cb73: Add more DEX tools, including remote captures 14 | 15 | ## 0.1.4 16 | 17 | ### Patch Changes 18 | 19 | - 7422e71: Update MCP sdk 20 | - Updated dependencies [7422e71] 21 | - @repo/mcp-observability@0.32.2 22 | - @repo/mcp-common@0.19.1 23 | 24 | ## 0.1.3 25 | 26 | ### Patch Changes 27 | 28 | - cc6d41f: Update agents deps & modelcontextprotocol 29 | - Updated dependencies [1833c6d] 30 | - Updated dependencies [cc6d41f] 31 | - @repo/mcp-common@0.19.0 32 | - @repo/mcp-observability@0.32.1 33 | 34 | ## 0.1.2 35 | 36 | ### Patch Changes 37 | 38 | - Updated dependencies [f885d07] 39 | - @repo/mcp-common@0.18.0 40 | 41 | ## 0.1.1 42 | 43 | ### Patch Changes 44 | 45 | - Updated dependencies [83e2d19] 46 | - @repo/mcp-common@0.17.1 47 | 48 | ## 0.1.0 49 | 50 | ### Minor Changes 51 | 52 | - 6cf52a6: Support AOT tokens 53 | 54 | ### Patch Changes 55 | 56 | - 0fc4439: Update agents and modelcontext dependencies 57 | - Updated dependencies [6cf52a6] 58 | - Updated dependencies [0fc4439] 59 | - @repo/mcp-observability@0.32.0 60 | - @repo/mcp-common@0.17.0 61 | 62 | ## 0.0.4 63 | 64 | ### Patch Changes 65 | 66 | - 3677a18: Remove extraneous log 67 | - Updated dependencies [3677a18] 68 | - @repo/mcp-common@0.16.3 69 | 70 | ## 0.0.3 71 | 72 | ### Patch Changes 73 | 74 | - 86c2e4f: Add API token passthrough auth 75 | - Updated dependencies [86c2e4f] 76 | - @repo/mcp-common@0.16.2 77 | 78 | ## 0.0.2 79 | 80 | ### Patch Changes 81 | 82 | - cf3771b: chore: add suffixes to common files in apps and packages 83 | 84 | 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. 85 | 86 | - Updated dependencies [cf3771b] 87 | - @repo/mcp-common@0.16.1 88 | - @repo/mcp-observability@0.31.1 89 | -------------------------------------------------------------------------------- /apps/dex-analysis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dex-analysis", 3 | "version": "0.1.6", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "run-wrangler-deploy", 9 | "dev": "wrangler dev", 10 | "start": "wrangler dev", 11 | "types": "wrangler types --include-env=false", 12 | "cf-typegen": "wrangler types", 13 | "test": "vitest run" 14 | }, 15 | "dependencies": { 16 | "@cloudflare/workers-oauth-provider": "0.0.5", 17 | "@hono/zod-validator": "0.4.3", 18 | "@modelcontextprotocol/sdk": "1.13.3", 19 | "@repo/mcp-common": "workspace:*", 20 | "@repo/mcp-observability": "workspace:*", 21 | "agents": "0.0.100", 22 | "cloudflare": "4.2.0", 23 | "hono": "4.7.6", 24 | "jszip": "3.10.1", 25 | "zod": "3.24.2" 26 | }, 27 | "devDependencies": { 28 | "@cloudflare/vitest-pool-workers": "0.8.14", 29 | "@types/jsonwebtoken": "9.0.9", 30 | "@types/node": "22.14.1", 31 | "prettier": "3.5.3", 32 | "typescript": "5.5.4", 33 | "vitest": "3.0.9", 34 | "wrangler": "4.10.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /apps/dex-analysis/src/dex-analysis.context.ts: -------------------------------------------------------------------------------- 1 | import type { UserDetails } from '@repo/mcp-common/src/durable-objects/user_details.do' 2 | import type { CloudflareDEXMCP } from './dex-analysis.app' 3 | import type { WarpDiagReader } from './warp_diag_reader' 4 | 5 | export interface Env { 6 | OAUTH_KV: KVNamespace 7 | ENVIRONMENT: 'development' | 'staging' | 'production' 8 | MCP_SERVER_NAME: string 9 | MCP_SERVER_VERSION: string 10 | CLOUDFLARE_CLIENT_ID: string 11 | CLOUDFLARE_CLIENT_SECRET: string 12 | MCP_OBJECT: DurableObjectNamespace 13 | USER_DETAILS: DurableObjectNamespace 14 | WARP_DIAG_READER: DurableObjectNamespace 15 | MCP_METRICS: AnalyticsEngineDataset 16 | DEV_DISABLE_OAUTH: string 17 | DEV_CLOUDFLARE_API_TOKEN: string 18 | DEV_CLOUDFLARE_EMAIL: string 19 | } 20 | -------------------------------------------------------------------------------- /apps/dex-analysis/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.ts", "./types.d.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/dex-analysis/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/dex-analysis/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/dex-analysis.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /apps/dns-analytics/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | DEV_CLOUDFLARE_API_TOKEN= -------------------------------------------------------------------------------- /apps/dns-analytics/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/dns-analytics/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # dns-analytics 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | - @repo/mcp-common@0.19.1 11 | 12 | ## 0.1.3 13 | 14 | ### Patch Changes 15 | 16 | - cc6d41f: Update agents deps & modelcontextprotocol 17 | - Updated dependencies [1833c6d] 18 | - Updated dependencies [cc6d41f] 19 | - @repo/mcp-common@0.19.0 20 | - @repo/mcp-observability@0.32.1 21 | 22 | ## 0.1.2 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [f885d07] 27 | - @repo/mcp-common@0.18.0 28 | 29 | ## 0.1.1 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [83e2d19] 34 | - @repo/mcp-common@0.17.1 35 | 36 | ## 0.1.0 37 | 38 | ### Minor Changes 39 | 40 | - 6cf52a6: Support AOT tokens 41 | 42 | ### Patch Changes 43 | 44 | - 0fc4439: Update agents and modelcontext dependencies 45 | - Updated dependencies [6cf52a6] 46 | - Updated dependencies [0fc4439] 47 | - @repo/mcp-observability@0.32.0 48 | - @repo/mcp-common@0.17.0 49 | 50 | ## 0.0.4 51 | 52 | ### Patch Changes 53 | 54 | - 3677a18: Remove extraneous log 55 | - Updated dependencies [3677a18] 56 | - @repo/mcp-common@0.16.3 57 | 58 | ## 0.0.3 59 | 60 | ### Patch Changes 61 | 62 | - 86c2e4f: Add API token passthrough auth 63 | - Updated dependencies [86c2e4f] 64 | - @repo/mcp-common@0.16.2 65 | 66 | ## 0.0.2 67 | 68 | ### Patch Changes 69 | 70 | - cf3771b: chore: add suffixes to common files in apps and packages 71 | 72 | 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. 73 | 74 | - Updated dependencies [cf3771b] 75 | - @repo/mcp-common@0.16.1 76 | - @repo/mcp-observability@0.31.1 77 | -------------------------------------------------------------------------------- /apps/dns-analytics/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | If you'd like to iterate and test your MCP server, you can do so in local development. 4 | 5 | ## Local Development 6 | 7 | 1. Create a `.dev.vars` file in your project root: 8 | 9 | If you're a Cloudflare employee: 10 | 11 | ``` 12 | CLOUDFLARE_CLIENT_ID=your_development_cloudflare_client_id 13 | CLOUDFLARE_CLIENT_SECRET=your_development_cloudflare_client_secret 14 | DEV_CLOUDFLARE_API_TOKEN=your_development_api_token 15 | ``` 16 | 17 | If you're an external contributor, you can provide a development API token (See [Cloudflare API](https://developers.cloudflare.com/api/) for information on creating an API Token): 18 | 19 | ``` 20 | DEV_DISABLE_OAUTH=true 21 | DEV_CLOUDFLARE_EMAIL=your_cloudflare_email 22 | # This is your api token with endpoint access. 23 | DEV_CLOUDFLARE_API_TOKEN=your_development_api_token 24 | ``` 25 | 26 | 2. Start the local development server: 27 | 28 | ```bash 29 | npx wrangler dev 30 | ``` 31 | 32 | 3. To test locally, open Inspector, and connect to `http://localhost:8976/sse`. 33 | Once you follow the prompts, you'll be able to "List Tools". You can also connect with any MCP client. 34 | 35 | ## Deploying the Worker ( Cloudflare employees only ) 36 | 37 | Set secrets via Wrangler: 38 | 39 | ```bash 40 | npx wrangler secret put CLOUDFLARE_CLIENT_ID -e 41 | npx wrangler secret put CLOUDFLARE_CLIENT_SECRET -e 42 | ``` 43 | 44 | ## Set up a KV namespace 45 | 46 | Create the KV namespace: 47 | 48 | ```bash 49 | npx wrangler kv namespace create "OAUTH_KV" 50 | ``` 51 | 52 | Then, update the Wrangler file with the generated KV namespace ID. 53 | 54 | ## Deploy & Test 55 | 56 | Deploy the MCP server to make it available on your workers.dev domain: 57 | 58 | ```bash 59 | npx wrangler deploy -e 60 | ``` 61 | 62 | Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector): 63 | 64 | ```bash 65 | npx @modelcontextprotocol/inspector@latest 66 | ``` 67 | -------------------------------------------------------------------------------- /apps/dns-analytics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dns-analytics", 3 | "version": "0.1.4", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "wrangler deploy", 9 | "dev": "wrangler dev", 10 | "start": "wrangler dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-common": "workspace:*", 19 | "@repo/mcp-observability": "workspace:*", 20 | "agents": "0.0.100", 21 | "cloudflare": "4.2.0", 22 | "hono": "4.7.6", 23 | "zod": "3.24.2" 24 | }, 25 | "devDependencies": { 26 | "@cloudflare/vitest-pool-workers": "0.8.14", 27 | "@types/node": "22.14.1", 28 | "prettier": "3.5.3", 29 | "typescript": "5.5.4", 30 | "vitest": "3.0.9", 31 | "wrangler": "4.10.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /apps/dns-analytics/src/dns-analytics.context.ts: -------------------------------------------------------------------------------- 1 | import type { UserDetails } from '@repo/mcp-common/src/durable-objects/user_details.do' 2 | import type { DNSAnalyticsMCP } from './dns-analytics.app' 3 | 4 | export interface Env { 5 | OAUTH_KV: KVNamespace 6 | ENVIRONMENT: 'development' | 'staging' | 'production' 7 | MCP_SERVER_NAME: string 8 | MCP_SERVER_VERSION: string 9 | CLOUDFLARE_CLIENT_ID: string 10 | CLOUDFLARE_CLIENT_SECRET: string 11 | MCP_OBJECT: DurableObjectNamespace 12 | USER_DETAILS: DurableObjectNamespace 13 | MCP_METRICS: AnalyticsEngineDataset 14 | SENTRY_ACCESS_CLIENT_ID: string 15 | SENTRY_ACCESS_CLIENT_SECRET: string 16 | GIT_HASH: string 17 | SENTRY_DSN: string 18 | DEV_DISABLE_OAUTH: string 19 | DEV_CLOUDFLARE_API_TOKEN: string 20 | DEV_CLOUDFLARE_EMAIL: string 21 | } 22 | -------------------------------------------------------------------------------- /apps/dns-analytics/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./worker-configuration.d.ts", "./types.d.ts", "./vitest.config.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/dns-analytics/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/dns-analytics/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | export interface TestEnv extends Env { 4 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 5 | CLOUDFLARE_MOCK_API_TOKEN: string 6 | } 7 | 8 | export default defineWorkersConfig({ 9 | test: { 10 | poolOptions: { 11 | workers: { 12 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 13 | miniflare: { 14 | bindings: { 15 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 16 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 17 | } satisfies Partial, 18 | }, 19 | }, 20 | }, 21 | }, 22 | }) 23 | -------------------------------------------------------------------------------- /apps/docs-autorag/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/docs-autorag/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # docs-autorag 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | - @repo/mcp-common@0.19.1 11 | 12 | ## 0.1.3 13 | 14 | ### Patch Changes 15 | 16 | - cc6d41f: Update agents deps & modelcontextprotocol 17 | - Updated dependencies [1833c6d] 18 | - Updated dependencies [cc6d41f] 19 | - @repo/mcp-common@0.19.0 20 | - @repo/mcp-observability@0.32.1 21 | 22 | ## 0.1.2 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [f885d07] 27 | - @repo/mcp-common@0.18.0 28 | 29 | ## 0.1.1 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [83e2d19] 34 | - @repo/mcp-common@0.17.1 35 | 36 | ## 0.1.0 37 | 38 | ### Minor Changes 39 | 40 | - 6cf52a6: Support AOT tokens 41 | 42 | ### Patch Changes 43 | 44 | - 0fc4439: Update agents and modelcontext dependencies 45 | - Updated dependencies [6cf52a6] 46 | - Updated dependencies [0fc4439] 47 | - @repo/mcp-observability@0.32.0 48 | - @repo/mcp-common@0.17.0 49 | 50 | ## 0.0.4 51 | 52 | ### Patch Changes 53 | 54 | - 3677a18: Remove extraneous log 55 | - Updated dependencies [3677a18] 56 | - @repo/mcp-common@0.16.3 57 | 58 | ## 0.0.3 59 | 60 | ### Patch Changes 61 | 62 | - Updated dependencies [86c2e4f] 63 | - @repo/mcp-common@0.16.2 64 | 65 | ## 0.0.2 66 | 67 | ### Patch Changes 68 | 69 | - cf3771b: chore: add suffixes to common files in apps and packages 70 | 71 | 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. 72 | 73 | - Updated dependencies [cf3771b] 74 | - @repo/mcp-common@0.16.1 75 | - @repo/mcp-observability@0.31.1 76 | -------------------------------------------------------------------------------- /apps/docs-autorag/README.md: -------------------------------------------------------------------------------- 1 | # Model Context Protocol (MCP) Server + Cloudflare Documentation (via Autorag) 2 | 3 | This is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) server that supports remote MCP connections. It connects to an autorag instance (in this case, Cloudflare docs) 4 | 5 | To run this server, you'll need access to an autorag instance which has indexed the contents of cloudflare-docs: https://github.com/cloudflare/cloudflare-docs/ 6 | 7 | The Cloudflare account this worker is deployed on already has this Autorag instance setup and indexed. 8 | 9 | ## Running locally 10 | 11 | ``` 12 | pnpm run start 13 | ``` 14 | 15 | Then connect to the server via remote MCP at `http://localhost:8976/sse` 16 | 17 | ## Deploying 18 | 19 | ``` 20 | pnpm run deploy --env [ENVIRONMENT] 21 | ``` 22 | -------------------------------------------------------------------------------- /apps/docs-autorag/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs-autorag", 3 | "version": "0.1.4", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "run-wrangler-deploy", 9 | "dev": "wrangler dev", 10 | "start": "wrangler dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-common": "workspace:*", 19 | "@repo/mcp-observability": "workspace:*", 20 | "agents": "0.0.100", 21 | "cloudflare": "4.2.0", 22 | "hono": "4.7.6", 23 | "mime": "4.0.6", 24 | "zod": "3.24.2" 25 | }, 26 | "devDependencies": { 27 | "@cloudflare/vitest-pool-workers": "0.8.14", 28 | "@types/node": "22.14.1", 29 | "prettier": "3.5.3", 30 | "typescript": "5.5.4", 31 | "vitest": "3.0.9", 32 | "wrangler": "4.10.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /apps/docs-autorag/src/docs-autorag.app.ts: -------------------------------------------------------------------------------- 1 | import { McpAgent } from 'agents/mcp' 2 | 3 | import { createApiHandler } from '@repo/mcp-common/src/api-handler' 4 | import { getEnv } from '@repo/mcp-common/src/env' 5 | import { CloudflareMCPServer } from '@repo/mcp-common/src/server' 6 | 7 | import { registerDocsTools } from './tools/docs-autorag.tools' 8 | 9 | import type { Env } from './docs-autorag.context' 10 | 11 | const env = getEnv() 12 | 13 | // The docs MCP server isn't stateful, so we don't have state/props 14 | export type Props = never 15 | 16 | export type State = never 17 | 18 | export class CloudflareDocumentationMCP extends McpAgent { 19 | server = new CloudflareMCPServer({ 20 | wae: env.MCP_METRICS, 21 | serverInfo: { 22 | name: env.MCP_SERVER_NAME, 23 | version: env.MCP_SERVER_VERSION, 24 | }, 25 | }) 26 | 27 | constructor( 28 | public ctx: DurableObjectState, 29 | public env: Env 30 | ) { 31 | super(ctx, env) 32 | } 33 | 34 | async init() { 35 | registerDocsTools(this) 36 | } 37 | } 38 | 39 | export default createApiHandler(CloudflareDocumentationMCP) 40 | -------------------------------------------------------------------------------- /apps/docs-autorag/src/docs-autorag.context.ts: -------------------------------------------------------------------------------- 1 | import type { CloudflareDocumentationMCP } from './docs-autorag.app' 2 | 3 | export interface Env { 4 | ENVIRONMENT: 'development' | 'staging' | 'production' 5 | AUTORAG_NAME: 'cloudflare-docs-autorag' 6 | MCP_SERVER_NAME: string 7 | MCP_SERVER_VERSION: string 8 | MCP_OBJECT: DurableObjectNamespace 9 | MCP_METRICS: AnalyticsEngineDataset 10 | AI: Ai 11 | } 12 | -------------------------------------------------------------------------------- /apps/docs-autorag/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/docs-autorag/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/docs-autorag.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /apps/docs-vectorize/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/docs-vectorize/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # docs-vectorize 2 | 3 | ## 0.3.2 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | - @repo/mcp-common@0.19.1 11 | 12 | ## 0.3.1 13 | 14 | ### Patch Changes 15 | 16 | - cc6d41f: Update agents deps & modelcontextprotocol 17 | - Updated dependencies [1833c6d] 18 | - Updated dependencies [cc6d41f] 19 | - @repo/mcp-common@0.19.0 20 | - @repo/mcp-observability@0.32.1 21 | 22 | ## 0.3.0 23 | 24 | ### Minor Changes 25 | 26 | - f885d07: Add search docs tool to bindings and obs servers 27 | 28 | ### Patch Changes 29 | 30 | - Updated dependencies [f885d07] 31 | - @repo/mcp-common@0.18.0 32 | 33 | ## 0.2.1 34 | 35 | ### Patch Changes 36 | 37 | - Updated dependencies [83e2d19] 38 | - @repo/mcp-common@0.17.1 39 | 40 | ## 0.2.0 41 | 42 | ### Minor Changes 43 | 44 | - 89bfaf4: feat: add Pages to Workers migration guide to docs-vectorize MCP server 45 | 46 | ## 0.1.0 47 | 48 | ### Minor Changes 49 | 50 | - 6cf52a6: Support AOT tokens 51 | 52 | ### Patch Changes 53 | 54 | - 0fc4439: Update agents and modelcontext dependencies 55 | - Updated dependencies [6cf52a6] 56 | - Updated dependencies [0fc4439] 57 | - @repo/mcp-observability@0.32.0 58 | - @repo/mcp-common@0.17.0 59 | 60 | ## 0.0.4 61 | 62 | ### Patch Changes 63 | 64 | - 3677a18: Remove extraneous log 65 | - Updated dependencies [3677a18] 66 | - @repo/mcp-common@0.16.3 67 | 68 | ## 0.0.3 69 | 70 | ### Patch Changes 71 | 72 | - Updated dependencies [86c2e4f] 73 | - @repo/mcp-common@0.16.2 74 | 75 | ## 0.0.2 76 | 77 | ### Patch Changes 78 | 79 | - cf3771b: chore: add suffixes to common files in apps and packages 80 | 81 | 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. 82 | 83 | - Updated dependencies [cf3771b] 84 | - @repo/mcp-common@0.16.1 85 | - @repo/mcp-observability@0.31.1 86 | -------------------------------------------------------------------------------- /apps/docs-vectorize/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs-vectorize", 3 | "version": "0.3.2", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "run-wrangler-deploy", 9 | "dev": "wrangler dev --experimental-vectorize-bind-to-prod", 10 | "start": "npm run dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-common": "workspace:*", 19 | "@repo/mcp-observability": "workspace:*", 20 | "agents": "0.0.100", 21 | "cloudflare": "4.2.0", 22 | "hono": "4.7.6", 23 | "mime": "4.0.6", 24 | "zod": "3.24.2" 25 | }, 26 | "devDependencies": { 27 | "@cloudflare/vitest-pool-workers": "0.8.14", 28 | "@types/node": "22.14.1", 29 | "prettier": "3.5.3", 30 | "typescript": "5.5.4", 31 | "vitest": "3.0.9", 32 | "wrangler": "4.10.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /apps/docs-vectorize/src/docs-vectorize.app.ts: -------------------------------------------------------------------------------- 1 | import { McpAgent } from 'agents/mcp' 2 | 3 | import { createApiHandler } from '@repo/mcp-common/src/api-handler' 4 | import { getEnv } from '@repo/mcp-common/src/env' 5 | import { registerPrompts } from '@repo/mcp-common/src/prompts/docs-vectorize.prompts' 6 | import { CloudflareMCPServer } from '@repo/mcp-common/src/server' 7 | import { registerDocsTools } from '@repo/mcp-common/src/tools/docs-vectorize.tools' 8 | 9 | import type { Env } from './docs-vectorize.context' 10 | 11 | const env = getEnv() 12 | 13 | // The docs MCP server isn't stateful, so we don't have state/props 14 | export type Props = never 15 | 16 | export type State = never 17 | 18 | export class CloudflareDocumentationMCP extends McpAgent { 19 | server = new CloudflareMCPServer({ 20 | wae: env.MCP_METRICS, 21 | serverInfo: { 22 | name: env.MCP_SERVER_NAME, 23 | version: env.MCP_SERVER_VERSION, 24 | }, 25 | }) 26 | 27 | constructor( 28 | public ctx: DurableObjectState, 29 | public env: Env 30 | ) { 31 | super(ctx, env) 32 | } 33 | 34 | async init() { 35 | registerDocsTools(this, this.env) 36 | registerPrompts(this) 37 | } 38 | } 39 | 40 | export default createApiHandler(CloudflareDocumentationMCP) 41 | -------------------------------------------------------------------------------- /apps/docs-vectorize/src/docs-vectorize.context.ts: -------------------------------------------------------------------------------- 1 | import type { CloudflareDocumentationMCP } from './docs-vectorize.app' 2 | 3 | export interface Env { 4 | ENVIRONMENT: 'development' | 'staging' | 'production' 5 | MCP_SERVER_NAME: string 6 | MCP_SERVER_VERSION: string 7 | MCP_OBJECT: DurableObjectNamespace 8 | MCP_METRICS: AnalyticsEngineDataset 9 | AI: Ai 10 | VECTORIZE: VectorizeIndex 11 | } 12 | -------------------------------------------------------------------------------- /apps/docs-vectorize/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/docs-vectorize/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/docs-vectorize.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /apps/graphql/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/graphql/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # graphql-mcp-server 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | - @repo/mcp-common@0.19.1 11 | 12 | ## 0.1.3 13 | 14 | ### Patch Changes 15 | 16 | - cc6d41f: Update agents deps & modelcontextprotocol 17 | - Updated dependencies [1833c6d] 18 | - Updated dependencies [cc6d41f] 19 | - @repo/mcp-common@0.19.0 20 | - @repo/mcp-observability@0.32.1 21 | 22 | ## 0.1.2 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [f885d07] 27 | - @repo/mcp-common@0.18.0 28 | 29 | ## 0.1.1 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [83e2d19] 34 | - @repo/mcp-common@0.17.1 35 | 36 | ## 0.1.0 37 | 38 | ### Minor Changes 39 | 40 | - 6cf52a6: Support AOT tokens 41 | 42 | ### Patch Changes 43 | 44 | - 0fc4439: Update agents and modelcontext dependencies 45 | - Updated dependencies [6cf52a6] 46 | - Updated dependencies [0fc4439] 47 | - @repo/mcp-observability@0.32.0 48 | - @repo/mcp-common@0.17.0 49 | 50 | ## 0.0.4 51 | 52 | ### Patch Changes 53 | 54 | - 3677a18: Remove extraneous log 55 | - Updated dependencies [3677a18] 56 | - @repo/mcp-common@0.16.3 57 | 58 | ## 0.0.3 59 | 60 | ### Patch Changes 61 | 62 | - 86c2e4f: Add API token passthrough auth 63 | - Updated dependencies [86c2e4f] 64 | - @repo/mcp-common@0.16.2 65 | 66 | ## 0.0.2 67 | 68 | ### Patch Changes 69 | 70 | - Updated dependencies [cf3771b] 71 | - @repo/mcp-common@0.16.1 72 | - @repo/mcp-observability@0.31.1 73 | -------------------------------------------------------------------------------- /apps/graphql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-mcp-server", 3 | "version": "0.1.4", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "run-wrangler-deploy", 9 | "dev": "wrangler dev", 10 | "start": "wrangler dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-common": "workspace:*", 19 | "@repo/mcp-observability": "workspace:*", 20 | "agents": "0.0.100", 21 | "cloudflare": "4.2.0", 22 | "hono": "4.7.6", 23 | "zod": "3.24.2", 24 | "lz-string": "1.5.0" 25 | }, 26 | "devDependencies": { 27 | "@cloudflare/vitest-pool-workers": "0.8.14", 28 | "@types/node": "22.14.1", 29 | "prettier": "3.5.3", 30 | "typescript": "5.5.4", 31 | "vitest": "3.0.9", 32 | "wrangler": "4.10.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /apps/graphql/src/graphql.context.ts: -------------------------------------------------------------------------------- 1 | import type { GraphQLMCP, UserDetails } from './graphql.app' 2 | 3 | export interface Env { 4 | OAUTH_KV: KVNamespace 5 | ENVIRONMENT: 'development' | 'staging' | 'production' 6 | MCP_SERVER_NAME: string 7 | MCP_SERVER_VERSION: string 8 | CLOUDFLARE_CLIENT_ID: string 9 | CLOUDFLARE_CLIENT_SECRET: string 10 | MCP_OBJECT: DurableObjectNamespace 11 | USER_DETAILS: DurableObjectNamespace 12 | MCP_METRICS: AnalyticsEngineDataset 13 | SENTRY_ACCESS_CLIENT_ID: string 14 | SENTRY_ACCESS_CLIENT_SECRET: string 15 | GIT_HASH: string 16 | SENTRY_DSN: string 17 | DEV_DISABLE_OAUTH: string 18 | DEV_CLOUDFLARE_API_TOKEN: string 19 | DEV_CLOUDFLARE_EMAIL: string 20 | } 21 | -------------------------------------------------------------------------------- /apps/graphql/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.ts", "./types.d.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/graphql/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/logpush/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | DEV_DISABLE_OAUTH= 4 | DEV_CLOUDFLARE_API_TOKEN= 5 | DEV_CLOUDFLARE_EMAIL= -------------------------------------------------------------------------------- /apps/logpush/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/logpush/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # logpush 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | - @repo/mcp-common@0.19.1 11 | 12 | ## 0.1.3 13 | 14 | ### Patch Changes 15 | 16 | - cc6d41f: Update agents deps & modelcontextprotocol 17 | - Updated dependencies [1833c6d] 18 | - Updated dependencies [cc6d41f] 19 | - @repo/mcp-common@0.19.0 20 | - @repo/mcp-observability@0.32.1 21 | 22 | ## 0.1.2 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [f885d07] 27 | - @repo/mcp-common@0.18.0 28 | 29 | ## 0.1.1 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [83e2d19] 34 | - @repo/mcp-common@0.17.1 35 | 36 | ## 0.1.0 37 | 38 | ### Minor Changes 39 | 40 | - 6cf52a6: Support AOT tokens 41 | 42 | ### Patch Changes 43 | 44 | - 0fc4439: Update agents and modelcontext dependencies 45 | - Updated dependencies [6cf52a6] 46 | - Updated dependencies [0fc4439] 47 | - @repo/mcp-observability@0.32.0 48 | - @repo/mcp-common@0.17.0 49 | 50 | ## 0.0.4 51 | 52 | ### Patch Changes 53 | 54 | - 3677a18: Remove extraneous log 55 | - Updated dependencies [3677a18] 56 | - @repo/mcp-common@0.16.3 57 | 58 | ## 0.0.3 59 | 60 | ### Patch Changes 61 | 62 | - 86c2e4f: Add API token passthrough auth 63 | - Updated dependencies [86c2e4f] 64 | - @repo/mcp-common@0.16.2 65 | 66 | ## 0.0.2 67 | 68 | ### Patch Changes 69 | 70 | - cf3771b: chore: add suffixes to common files in apps and packages 71 | 72 | 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. 73 | 74 | - Updated dependencies [cf3771b] 75 | - @repo/mcp-common@0.16.1 76 | - @repo/mcp-observability@0.31.1 77 | -------------------------------------------------------------------------------- /apps/logpush/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "logpush", 3 | "version": "0.1.4", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "wrangler deploy", 9 | "dev": "wrangler dev", 10 | "start": "wrangler dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-common": "workspace:*", 19 | "@repo/mcp-observability": "workspace:*", 20 | "agents": "0.0.100", 21 | "cloudflare": "4.2.0", 22 | "hono": "4.7.6", 23 | "zod": "3.24.2" 24 | }, 25 | "devDependencies": { 26 | "@cloudflare/vitest-pool-workers": "0.8.14", 27 | "@types/node": "22.14.1", 28 | "prettier": "3.5.3", 29 | "typescript": "5.5.4", 30 | "vitest": "3.0.9", 31 | "wrangler": "4.10.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /apps/logpush/src/logpush.context.ts: -------------------------------------------------------------------------------- 1 | import type { UserDetails } from '@repo/mcp-common/src/durable-objects/user_details.do' 2 | import type { LogsMCP } from './logpush.app' 3 | 4 | export interface Env { 5 | OAUTH_KV: KVNamespace 6 | ENVIRONMENT: 'development' | 'staging' | 'production' 7 | MCP_SERVER_NAME: string 8 | MCP_SERVER_VERSION: string 9 | CLOUDFLARE_CLIENT_ID: string 10 | CLOUDFLARE_CLIENT_SECRET: string 11 | MCP_OBJECT: DurableObjectNamespace 12 | USER_DETAILS: DurableObjectNamespace 13 | MCP_METRICS: AnalyticsEngineDataset 14 | DEV_DISABLE_OAUTH: string 15 | DEV_CLOUDFLARE_API_TOKEN: string 16 | DEV_CLOUDFLARE_EMAIL: string 17 | } 18 | -------------------------------------------------------------------------------- /apps/logpush/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.ts", "./types.d.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/logpush/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/logpush/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/logpush.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /apps/radar/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | DEV_DISABLE_OAUTH= 4 | DEV_CLOUDFLARE_API_TOKEN= 5 | DEV_CLOUDFLARE_EMAIL= 6 | -------------------------------------------------------------------------------- /apps/radar/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/radar/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # cloudflare-radar-mcp-server 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | - @repo/mcp-common@0.19.1 11 | 12 | ## 0.1.3 13 | 14 | ### Patch Changes 15 | 16 | - cc6d41f: Update agents deps & modelcontextprotocol 17 | - Updated dependencies [1833c6d] 18 | - Updated dependencies [cc6d41f] 19 | - @repo/mcp-common@0.19.0 20 | - @repo/mcp-observability@0.32.1 21 | 22 | ## 0.1.2 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [f885d07] 27 | - @repo/mcp-common@0.18.0 28 | 29 | ## 0.1.1 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [83e2d19] 34 | - @repo/mcp-common@0.17.1 35 | 36 | ## 0.1.0 37 | 38 | ### Minor Changes 39 | 40 | - 6cf52a6: Support AOT tokens 41 | 42 | ### Patch Changes 43 | 44 | - 0fc4439: Update agents and modelcontext dependencies 45 | - Updated dependencies [6cf52a6] 46 | - Updated dependencies [0fc4439] 47 | - @repo/mcp-observability@0.32.0 48 | - @repo/mcp-common@0.17.0 49 | 50 | ## 0.0.4 51 | 52 | ### Patch Changes 53 | 54 | - 3677a18: Remove extraneous log 55 | - Updated dependencies [3677a18] 56 | - @repo/mcp-common@0.16.3 57 | 58 | ## 0.0.3 59 | 60 | ### Patch Changes 61 | 62 | - 86c2e4f: Add API token passthrough auth 63 | - Updated dependencies [86c2e4f] 64 | - @repo/mcp-common@0.16.2 65 | 66 | ## 0.0.2 67 | 68 | ### Patch Changes 69 | 70 | - cf3771b: chore: add suffixes to common files in apps and packages 71 | 72 | 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. 73 | 74 | - Updated dependencies [cf3771b] 75 | - @repo/mcp-common@0.16.1 76 | - @repo/mcp-observability@0.31.1 77 | -------------------------------------------------------------------------------- /apps/radar/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | If you'd like to iterate and test your MCP server, you can do so in local development. 4 | 5 | ## Local Development 6 | 7 | 1. Create a `.dev.vars` file in your project root: 8 | 9 | If you're a Cloudflare employee: 10 | 11 | ``` 12 | CLOUDFLARE_CLIENT_ID=your_development_cloudflare_client_id 13 | CLOUDFLARE_CLIENT_SECRET=your_development_cloudflare_client_secret 14 | ``` 15 | 16 | If you're an external contributor, you can provide a development API token: 17 | 18 | ``` 19 | DEV_DISABLE_OAUTH=true 20 | DEV_CLOUDFLARE_EMAIL=your_cloudflare_email 21 | # This is your global api token 22 | DEV_CLOUDFLARE_API_TOKEN=your_development_api_token 23 | ``` 24 | 25 | 2. Start the local development server: 26 | 27 | ```bash 28 | npx wrangler dev 29 | ``` 30 | 31 | 3. To test locally, open Inspector, and connect to `http://localhost:8976/sse`. 32 | Once you follow the prompts, you'll be able to "List Tools". You can also connect with any MCP client. 33 | 34 | ## Deploying the Worker ( Cloudflare employees only ) 35 | 36 | Set secrets via Wrangler: 37 | 38 | ```bash 39 | npx wrangler secret put CLOUDFLARE_CLIENT_ID -e 40 | npx wrangler secret put CLOUDFLARE_CLIENT_SECRET -e 41 | ``` 42 | 43 | ## Set up a KV namespace 44 | 45 | Create the KV namespace: 46 | 47 | ```bash 48 | npx wrangler kv namespace create "OAUTH_KV" 49 | ``` 50 | 51 | Then, update the Wrangler file with the generated KV namespace ID. 52 | 53 | ## Deploy & Test 54 | 55 | Deploy the MCP server to make it available on your workers.dev domain: 56 | 57 | ```bash 58 | npx wrangler deploy -e 59 | ``` 60 | 61 | Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector): 62 | 63 | ```bash 64 | npx @modelcontextprotocol/inspector@latest 65 | ``` 66 | -------------------------------------------------------------------------------- /apps/radar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloudflare-radar-mcp-server", 3 | "version": "0.1.4", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "run-wrangler-deploy", 9 | "dev": "wrangler dev", 10 | "start": "wrangler dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-common": "workspace:*", 19 | "@repo/mcp-observability": "workspace:*", 20 | "agents": "0.0.100", 21 | "cloudflare": "4.2.0", 22 | "hono": "4.7.6", 23 | "zod": "3.24.2" 24 | }, 25 | "devDependencies": { 26 | "@cloudflare/vitest-pool-workers": "0.8.14", 27 | "@types/node": "22.14.1", 28 | "prettier": "3.5.3", 29 | "typescript": "5.5.4", 30 | "vitest": "3.0.9", 31 | "wrangler": "4.10.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /apps/radar/src/radar.context.ts: -------------------------------------------------------------------------------- 1 | import type { RadarMCP, UserDetails } from './radar.app' 2 | 3 | export interface Env { 4 | OAUTH_KV: KVNamespace 5 | ENVIRONMENT: 'development' | 'staging' | 'production' 6 | MCP_SERVER_NAME: string 7 | MCP_SERVER_VERSION: string 8 | CLOUDFLARE_CLIENT_ID: string 9 | CLOUDFLARE_CLIENT_SECRET: string 10 | MCP_OBJECT: DurableObjectNamespace 11 | USER_DETAILS: DurableObjectNamespace 12 | MCP_METRICS: AnalyticsEngineDataset 13 | DEV_DISABLE_OAUTH: string 14 | DEV_CLOUDFLARE_API_TOKEN: string 15 | DEV_CLOUDFLARE_EMAIL: string 16 | } 17 | 18 | export const BASE_INSTRUCTIONS = /* markdown */ ` 19 | # Cloudflare Radar MCP Server 20 | 21 | This server integrates tools powered by the Cloudflare Radar API to provide insights into global Internet traffic, 22 | trends, and other related utilities. 23 | 24 | An active account is **only required** for URL Scanner-related tools (e.g., \`scan_url\`). 25 | 26 | For tools related to Internet trends and insights, analyze the results and, when appropriate, generate visualizations 27 | such as line charts, pie charts, bar charts, stacked area charts, choropleth maps, treemaps, or other relevant chart types. 28 | 29 | ### Making comparisons 30 | 31 | Many tools support **array-based filters** to enable comparisons across multiple criteria. 32 | In such cases, the array index corresponds to a distinct data series. 33 | For each data series, provide a corresponding \`dateRange\`, or alternatively a \`dateStart\` and \`dateEnd\` pair. 34 | Example: To compare HTTP traffic between Portugal and Spain over the last 7 days: 35 | - \`dateRange: ["7d", "7d"]\` 36 | - \`location: ["PT", "ES"]\` 37 | 38 | This applies to date filters and other filters that support comparison across multiple values. 39 | If a tool does **not** support array-based filters, you can achieve the same comparison by making multiple separate 40 | calls to the tool. 41 | ` 42 | -------------------------------------------------------------------------------- /apps/radar/src/types/url-scanner.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file contains the validators for the URL scanner tools. 3 | */ 4 | import { z } from 'zod' 5 | 6 | export const UrlParam = z 7 | .string() 8 | .url() 9 | .describe('A valid URL including protocol (e.g., "https://example.com").') 10 | 11 | export const CreateScanResult = z 12 | .object({ 13 | uuid: z.string(), 14 | }) 15 | .passthrough() 16 | -------------------------------------------------------------------------------- /apps/radar/src/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Resolves and invokes a method dynamically based on the provided slugs. 3 | * 4 | * This function traverses the object based on the `slugs` array, binds the method 5 | * to its correct context, and invokes it with the provided parameters. 6 | * 7 | * @param {Object} client - The root object (e.g., `client.radar.http`) to resolve methods from. 8 | * @param {string[]} path - The path to the desired method. 9 | * @param {Object} params - The parameters to pass when invoking the resolved method. 10 | * @returns {Promise} The result of the method invocation. 11 | */ 12 | export async function resolveAndInvoke(client: any, path: string, params: any): Promise { 13 | const slugs = path.split('/') 14 | const method = slugs.reduce((acc, key) => acc?.[key], client) 15 | const parentContext = slugs.slice(0, -1).reduce((acc, key) => acc?.[key], client) 16 | return await method.bind(parentContext)(params) 17 | } 18 | -------------------------------------------------------------------------------- /apps/radar/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.ts", "./types.d.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/radar/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/radar/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/radar.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /apps/sandbox-container/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | DEV_DISABLE_OAUTH= 4 | DEV_CLOUDFLARE_API_TOKEN= 5 | DEV_CLOUDFLARE_EMAIL= -------------------------------------------------------------------------------- /apps/sandbox-container/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/sandbox-container/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Container MCP Server 2 | 3 | This is a simple MCP-based interface for a sandboxed development environment. 4 | 5 | ## Local dev 6 | 7 | Cloudchamber local dev isn't implemented yet, so we are doing a bit of a hack to just run the server in your local environment. Because of this, testing the container(s) and container manager locally is not possible at this time. 8 | 9 | Do the following from within the sandbox-container app: 10 | 11 | 1. Copy the `.dev.vars.example` file to a new `.dev.vars` file. 12 | 2. Get the Cloudflare client id and secret from a team member and add them to the `.dev.vars` file. 13 | 3. Run `pnpm i` then `pnpm dev` to start the MCP server. 14 | 4. Run `pnpx @modelcontextprotocol/inspector` to start the MCP inspector client. 15 | 5. Open the inspector client in your browser and connect to the server via `http://localhost:8976/sse`. 16 | 17 | Note: Temporary files created through files tool calls are stored in the workdir folder of this app. 18 | 19 | ## Deploying 20 | 21 | 1. Make sure the docker daemon is running 22 | 23 | 2. Disable WARP and run 24 | 25 | ``` 26 | npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/14387504770/npm-package-wrangler-8740 deploy 27 | ``` 28 | 29 | 3. Add to your Claude config. If using with Claude, you'll need to disable WARP: 30 | 31 | ``` 32 | { 33 | "mcpServers": { 34 | "container": { 35 | "command": "npx", 36 | "args": [ 37 | "mcp-remote", 38 | // this is my deployed instance 39 | "https://container-starter-2.cmsparks.workers.dev/sse" 40 | ] 41 | } 42 | } 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /apps/sandbox-container/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use Alpine as base for minimal size 2 | FROM alpine:3.19 as base 3 | 4 | # Install necessary packages while minimizing layers 5 | # We combine commands with && and clean cache in the same layer 6 | # to reduce the image size 7 | RUN apk update && \ 8 | apk add --no-cache \ 9 | # Core utilities 10 | git \ 11 | curl \ 12 | wget \ 13 | # Build essentials 14 | build-base \ 15 | # Python and pip 16 | python3 \ 17 | py3-pip \ 18 | # Node and npm 19 | nodejs \ 20 | npm && \ 21 | # Clean up the cache to reduce image size 22 | rm -rf /var/cache/apk/* && \ 23 | # Create symlink for python 24 | ln -sf /usr/bin/python3 /usr/bin/python 25 | 26 | # Install pnpm in a separate layer for better caching 27 | RUN npm install -g pnpm && \ 28 | rm -rf /root/.npm 29 | 30 | # Set up pnpm environment 31 | ENV PNPM_HOME=/usr/local/bin 32 | ENV PATH=$PNPM_HOME:$PATH 33 | 34 | # Set working directory 35 | WORKDIR /app 36 | 37 | # Set environment variables 38 | ENV PATH="/app/node_modules/.bin:${PATH}" 39 | 40 | ### 41 | # STAGE: PRUNE - Generate a partial monorepo for the sandbox-container app. The output will be placed into a directory named "out" 42 | ### 43 | FROM base AS prune 44 | WORKDIR /app 45 | RUN pnpm install turbo --global 46 | COPY . . 47 | RUN turbo prune containers-starter 48 | 49 | ### 50 | # STAGE: INSTALL & RUN 51 | ### 52 | FROM base AS installer 53 | WORKDIR /app 54 | 55 | COPY --from=prune /app/out/ . 56 | RUN pnpm install --frozen-lockfile --only=production 57 | 58 | WORKDIR /app/apps/sandbox-container 59 | 60 | # Expose the port your Node.js server will run on 61 | EXPOSE 8080 62 | 63 | CMD ["pnpm", "run", "start:container"] 64 | -------------------------------------------------------------------------------- /apps/sandbox-container/container/fileUtils.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'node:fs/promises' 2 | import path from 'node:path' 3 | import mime from 'mime' 4 | 5 | // this is because there isn't a "real" directory mime type, so we're reusing the "text/directory" mime type 6 | // so claude doesn't give an error 7 | export const DIRECTORY_CONTENT_TYPE = 'text/directory' 8 | 9 | export async function get_file_name_from_path(path: string): Promise { 10 | path = path.replace('/files/contents', '') 11 | path = path.endsWith('/') ? path.substring(0, path.length - 1) : path 12 | 13 | return path 14 | } 15 | 16 | export async function list_files_in_directory(dirPath: string): Promise { 17 | const files: string[] = [] 18 | try { 19 | const dir = await fs.readdir(path.join(process.cwd(), dirPath), { 20 | withFileTypes: true, 21 | }) 22 | for (const dirent of dir) { 23 | const relPath = path.relative(process.cwd(), `${dirPath}/${dirent.name}`) 24 | files.push(`file:///${relPath}`) 25 | } 26 | } catch (error) { 27 | throw new Error('Failed to read directory') 28 | } 29 | 30 | return files 31 | } 32 | 33 | export async function get_mime_type(path: string): Promise { 34 | let mimeType = mime.getType(path) 35 | if (mimeType && mimeType === 'inode/directory') { 36 | mimeType = DIRECTORY_CONTENT_TYPE 37 | } 38 | return mimeType 39 | } 40 | -------------------------------------------------------------------------------- /apps/sandbox-container/container/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["es2023"], 4 | "module": "ES2022", 5 | "target": "es2022", 6 | "types": ["@types/node"], 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "skipLibCheck": true, 10 | "moduleResolution": "bundler", 11 | "noEmit": true, 12 | "allowImportingTsExtensions": true 13 | }, 14 | "include": ["**/*.ts"], 15 | "exclude": [] 16 | } 17 | -------------------------------------------------------------------------------- /apps/sandbox-container/evals/exec.eval.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'vitest' 2 | import { describeEval } from 'vitest-evals' 3 | 4 | import { runTask } from '@repo/eval-tools/src/runTask' 5 | import { checkFactuality } from '@repo/eval-tools/src/scorers' 6 | import { eachModel } from '@repo/eval-tools/src/test-models' 7 | 8 | import { initializeClient } from './utils' 9 | 10 | eachModel('$modelName', ({ model }) => { 11 | describeEval('Runs a python file in a container', { 12 | data: async () => [ 13 | { 14 | input: 'Create a hello world python script and run it', 15 | expected: `The container_file_write tool was called, containing a file ending in .py.\ 16 | Then the container_file_exec tool was called with python or python3 as one of the arguments`, 17 | }, 18 | ], 19 | task: async (input) => { 20 | const client = await initializeClient() 21 | const { promptOutput, toolCalls } = await runTask(client, model, input) 22 | 23 | expect(toolCalls).toEqual( 24 | expect.arrayContaining([ 25 | expect.objectContaining({ 26 | type: 'tool-call', 27 | toolName: 'container_exec', 28 | args: { 29 | args: expect.objectContaining({ 30 | args: expect.stringContaining('python'), 31 | }), 32 | }, 33 | }), 34 | ]) 35 | ) 36 | 37 | expect(toolCalls).toEqual( 38 | expect.arrayContaining([ 39 | expect.objectContaining({ 40 | type: 'tool-call', 41 | toolName: 'container_file_write', 42 | args: { 43 | args: expect.objectContaining({ 44 | path: expect.stringContaining('.py'), 45 | }), 46 | }, 47 | }), 48 | ]) 49 | ) 50 | 51 | return promptOutput 52 | }, 53 | scorers: [checkFactuality], 54 | threshold: 1, 55 | timeout: 60000, 56 | }) 57 | }) 58 | -------------------------------------------------------------------------------- /apps/sandbox-container/evals/initialize.eval.ts: -------------------------------------------------------------------------------- 1 | import { describeEval } from 'vitest-evals' 2 | 3 | import { runTask } from '@repo/eval-tools/src/runTask' 4 | import { checkFactuality } from '@repo/eval-tools/src/scorers' 5 | import { eachModel } from '@repo/eval-tools/src/test-models' 6 | 7 | import { initializeClient } from './utils' 8 | 9 | eachModel('$modelName', ({ model }) => { 10 | describeEval('Runs container initialize', { 11 | data: async () => [ 12 | { 13 | input: 'create and ping a container', 14 | expected: 15 | 'The container_initialize tool was called and then the container_ping tool was called', 16 | }, 17 | ], 18 | task: async (input) => { 19 | const client = await initializeClient() 20 | const { promptOutput } = await runTask(client, model, input) 21 | return promptOutput 22 | }, 23 | scorers: [checkFactuality], 24 | threshold: 1, 25 | timeout: 60000, 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /apps/sandbox-container/evals/utils.ts: -------------------------------------------------------------------------------- 1 | import { MCPClientManager } from 'agents/mcp/client' 2 | 3 | export async function initializeClient(): Promise { 4 | const clientManager = new MCPClientManager('test-client', '0.0.0') 5 | await clientManager.connect('http://localhost:8976/sse') 6 | return clientManager 7 | } 8 | -------------------------------------------------------------------------------- /apps/sandbox-container/server/metrics.ts: -------------------------------------------------------------------------------- 1 | import { MetricsEvent, MetricsEventIndexIds } from '@repo/mcp-observability' 2 | 3 | export class ContainerEvent extends MetricsEvent { 4 | constructor( 5 | private containers: { 6 | active?: number 7 | } 8 | ) { 9 | super() 10 | } 11 | 12 | toDataPoint(): AnalyticsEngineDataPoint { 13 | return { 14 | indexes: [MetricsEventIndexIds.CONTAINER_MANAGER], 15 | doubles: this.mapDoubles({ 16 | double1: this.containers.active, 17 | }), 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /apps/sandbox-container/server/sandbox.server.context.ts: -------------------------------------------------------------------------------- 1 | import type { ContainerManager, ContainerMcpAgent, UserContainer } from './sandbox.server.app' 2 | 3 | export interface Env { 4 | OAUTH_KV: KVNamespace 5 | CLOUDFLARE_CLIENT_ID: string 6 | CLOUDFLARE_CLIENT_SECRET: string 7 | ENVIRONMENT: 'dev' 8 | MCP_SERVER_NAME: string 9 | MCP_SERVER_VERSION: string 10 | OPENAI_API_KEY: string 11 | AI_GATEWAY_TOKEN: string 12 | CLOUDFLARE_ACCOUNT_ID: string 13 | AI_GATEWAY_ID: string 14 | MCP_OBJECT: DurableObjectNamespace 15 | CONTAINER_MANAGER: DurableObjectNamespace 16 | USER_CONTAINER: DurableObjectNamespace 17 | USER_BLOCKLIST: KVNamespace 18 | MCP_METRICS: AnalyticsEngineDataset 19 | AI: Ai 20 | DEV_DISABLE_OAUTH: string 21 | DEV_CLOUDFLARE_API_TOKEN: string 22 | DEV_CLOUDFLARE_EMAIL: string 23 | } 24 | -------------------------------------------------------------------------------- /apps/sandbox-container/server/utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | import { stripProtocolFromFilePath } from './utils' 4 | 5 | describe('get_file_name_from_path', () => { 6 | it('strips file:// protocol from path', async () => { 7 | const path = await stripProtocolFromFilePath('file:///files/contents/cats') 8 | expect(path).toBe('/files/contents/cats') 9 | }), 10 | it('leaves protocol-less paths untouched', async () => { 11 | const path = await stripProtocolFromFilePath('/files/contents/cats') 12 | expect(path).toBe('/files/contents/cats') 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /apps/sandbox-container/server/utils.ts: -------------------------------------------------------------------------------- 1 | export async function fileToBase64(blob: Blob): Promise { 2 | // Use ArrayBuffer instead of text() for binary data 3 | const arrayBuffer = await blob.arrayBuffer() 4 | const byteArray = new Uint8Array(arrayBuffer) 5 | 6 | // Convert byte array to base64 string 7 | let binary = '' 8 | byteArray.forEach((byte) => { 9 | binary += String.fromCharCode(byte) 10 | }) 11 | 12 | // Apply base64 encoding 13 | return btoa(binary) 14 | } 15 | 16 | // Used for file related tool calls in case the llm sends a full resource URI 17 | export async function stripProtocolFromFilePath(path: string): Promise { 18 | return path.startsWith('file://') ? path.replace('file://', '') : path 19 | } 20 | -------------------------------------------------------------------------------- /apps/sandbox-container/shared/consts.ts: -------------------------------------------------------------------------------- 1 | // Set this to the open port on your container 2 | export const OPEN_CONTAINER_PORT = 8080 3 | -------------------------------------------------------------------------------- /apps/sandbox-container/shared/schema.ts: -------------------------------------------------------------------------------- 1 | import z from 'zod' 2 | 3 | export type ExecParams = z.infer 4 | export const ExecParams = z.object({ 5 | args: z.string(), 6 | timeout: z.number().optional().describe('Timeout in milliseconds'), 7 | streamStderr: z.boolean().default(true), 8 | }) 9 | 10 | export type FileWrite = z.infer 11 | export const FileWrite = z.object({ 12 | path: z.string(), 13 | text: z.string().describe('Full text content of the file you want to write.'), 14 | }) 15 | 16 | export type FilePathParam = z.infer 17 | export const FilePathParam = z.object({ 18 | path: z.string(), 19 | }) 20 | 21 | export type FileList = z.infer 22 | export const FileList = z.object({ 23 | resources: z 24 | .object({ 25 | uri: z.string(), 26 | name: z.string(), 27 | description: z.string().optional(), 28 | mimeType: z.string().optional(), 29 | }) 30 | .array(), 31 | }) 32 | 33 | export type FilesContextSchema = z.infer 34 | export const FilesContextSchema = z.object({ 35 | files: z 36 | .object({ 37 | uri: z.string(), 38 | }) 39 | .array(), 40 | }) 41 | -------------------------------------------------------------------------------- /apps/sandbox-container/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.evals.ts", "./types.d.ts"], 4 | "exclude": ["container/**.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /apps/sandbox-container/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'cloudflare:test' { 2 | interface ProvidedEnv { 3 | OPENAI_API_KEY: 'TODO' 4 | AI_GATEWAY_TOKEN: string 5 | CLOUDFLARE_ACCOUNT_ID: string 6 | AI_GATEWAY_ID: string 7 | AI: Ai 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /apps/sandbox-container/vitest.config.evals.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | export default defineWorkersConfig({ 4 | test: { 5 | include: ['**/*.eval.?(c|m)[jt]s?(x)'], 6 | poolOptions: { 7 | workers: { 8 | isolatedStorage: true, 9 | wrangler: { configPath: './wrangler.jsonc' }, 10 | miniflare: { 11 | bindings: { 12 | ENVIRONMENT: 'test', 13 | }, 14 | }, 15 | }, 16 | }, 17 | }, 18 | }) 19 | -------------------------------------------------------------------------------- /apps/workers-bindings/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | DEV_DISABLE_OAUTH= 4 | DEV_CLOUDFLARE_API_TOKEN= 5 | DEV_CLOUDFLARE_EMAIL= -------------------------------------------------------------------------------- /apps/workers-bindings/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/workers-bindings/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | If you'd like to iterate and test your MCP server, you can do so in local development. 4 | 5 | ## Local Development 6 | 7 | 1. Create a `.dev.vars` file in your project root: 8 | 9 | If you're a Cloudflare employee: 10 | 11 | ``` 12 | CLOUDFLARE_CLIENT_ID=your_development_cloudflare_client_id 13 | CLOUDFLARE_CLIENT_SECRET=your_development_cloudflare_client_secret 14 | ``` 15 | 16 | If you're an external contributor, you can provide a development API token: 17 | 18 | ``` 19 | DEV_DISABLE_OAUTH=true 20 | DEV_CLOUDFLARE_EMAIL=your_cloudflare_email 21 | # This is your global api token 22 | DEV_CLOUDFLARE_API_TOKEN=your_development_api_token 23 | ``` 24 | 25 | 2. Start the local development server: 26 | 27 | ```bash 28 | npx wrangler dev 29 | ``` 30 | 31 | 3. To test locally, open Inspector, and connect to `http://localhost:8976/sse`. 32 | Once you follow the prompts, you'll be able to "List Tools". You can also connect with any MCP client. 33 | 34 | ## Deploying the Worker ( Cloudflare employees only ) 35 | 36 | Set secrets via Wrangler: 37 | 38 | ```bash 39 | npx wrangler secret put CLOUDFLARE_CLIENT_ID -e 40 | npx wrangler secret put CLOUDFLARE_CLIENT_SECRET -e 41 | ``` 42 | 43 | ## Set up a KV namespace 44 | 45 | Create the KV namespace: 46 | 47 | ```bash 48 | npx wrangler kv namespace create "OAUTH_KV" 49 | ``` 50 | 51 | Then, update the Wrangler file with the generated KV namespace ID. 52 | 53 | ## Deploy & Test 54 | 55 | Deploy the MCP server to make it available on your workers.dev domain: 56 | 57 | ```bash 58 | npx wrangler deploy -e 59 | ``` 60 | 61 | Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector): 62 | 63 | ```bash 64 | npx @modelcontextprotocol/inspector@latest 65 | ``` 66 | -------------------------------------------------------------------------------- /apps/workers-bindings/evals/hyperdrive.eval.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'vitest' 2 | import { describeEval } from 'vitest-evals' 3 | 4 | import { runTask } from '@repo/eval-tools/src/runTask' 5 | import { checkFactuality } from '@repo/eval-tools/src/scorers' 6 | import { eachModel } from '@repo/eval-tools/src/test-models' 7 | import { HYPERDRIVE_TOOLS } from '@repo/mcp-common/src/tools/hyperdrive.tools' 8 | 9 | import { initializeClient } from './utils' // Assuming utils.ts will exist here 10 | 11 | // 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 12 | // const HYPERDRIVE_NAME = 'neon-test-hyperdrive' 13 | // const HYPERDRIVE_DATABASE = 'neondb' 14 | // const HYPERDRIVE_HOST = 'ep-late-cell-a4fm3g5p-pooler.us-east-1.aws.neon.tech' 15 | // const HYPERDRIVE_PORT = 5432 16 | // const HYPERDRIVE_USER = 'neondb_owner' 17 | // const HYPERDRIVE_PASSWORD = 'my-test-password' 18 | 19 | eachModel('$modelName', ({ model }) => { 20 | describeEval('Hyperdrive Tool Evaluations', { 21 | data: async () => [ 22 | { 23 | input: `List my hyperdrive configurations.`, 24 | expected: `The ${HYPERDRIVE_TOOLS.hyperdrive_configs_list} tool should be called to list my hyperdrive configurations.`, 25 | }, 26 | ], 27 | task: async (input: string) => { 28 | const client = await initializeClient(/* Pass necessary mocks/config */) 29 | const { promptOutput, toolCalls } = await runTask(client, model, input) 30 | 31 | const toolCall = toolCalls.find( 32 | (call) => call.toolName === HYPERDRIVE_TOOLS.hyperdrive_configs_list 33 | ) 34 | expect( 35 | toolCall, 36 | `Tool ${HYPERDRIVE_TOOLS.hyperdrive_configs_list} was not called` 37 | ).toBeDefined() 38 | 39 | return promptOutput 40 | }, 41 | scorers: [checkFactuality], 42 | threshold: 1, 43 | timeout: 60000, 44 | }) 45 | }) 46 | -------------------------------------------------------------------------------- /apps/workers-bindings/evals/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from '../vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/workers-bindings/evals/utils.ts: -------------------------------------------------------------------------------- 1 | import { MCPClientManager } from 'agents/mcp/client' 2 | 3 | export async function initializeClient(): Promise { 4 | const clientManager = new MCPClientManager('test-client', '0.0.0') 5 | await clientManager.connect('http://localhost:8977/sse') 6 | return clientManager 7 | } 8 | -------------------------------------------------------------------------------- /apps/workers-bindings/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "workers-bindings", 3 | "version": "0.3.2", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "wrangler deploy", 9 | "deploy:staging": "wrangler deploy --env staging", 10 | "deploy:production": "wrangler deploy --env production", 11 | "eval:dev": "start-server-and-test --expect 404 eval:server http://localhost:8977 'vitest --testTimeout=60000 --config vitest.config.evals.ts'", 12 | "eval:server": "wrangler dev --var ENVIRONMENT:test --var DEV_DISABLE_OAUTH:true --var DEV_CLOUDFLARE_EMAIL:mcp-server-eval-account@workers-for-platforms-dev.cfdata.org --inspector-port 9230 --port 8977", 13 | "eval:ci": "start-server-and-test --expect 404 eval:server http://localhost:8977 'vitest run --testTimeout=60000 --config vitest.config.evals.ts'", 14 | "dev": "wrangler dev", 15 | "start": "wrangler dev", 16 | "types": "wrangler types --include-env=false", 17 | "test": "vitest" 18 | }, 19 | "devDependencies": { 20 | "@cloudflare/vitest-pool-workers": "0.8.14", 21 | "@types/node": "22.14.1", 22 | "marked": "15.0.7", 23 | "typescript": "5.5.4", 24 | "vitest": "3.0.9", 25 | "wrangler": "4.10.0" 26 | }, 27 | "dependencies": { 28 | "@cloudflare/workers-oauth-provider": "0.0.5", 29 | "@modelcontextprotocol/sdk": "1.13.3", 30 | "@n8n/json-schema-to-zod": "1.1.0", 31 | "@repo/eval-tools": "workspace:*", 32 | "@repo/mcp-common": "workspace:*", 33 | "@repo/mcp-observability": "workspace:*", 34 | "agents": "0.0.100", 35 | "ai": "4.3.10", 36 | "concurrently": "9.1.2", 37 | "hono": "4.7.6", 38 | "start-server-and-test": "2.0.11", 39 | "vitest-evals": "0.1.4", 40 | "zod": "3.24.2" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /apps/workers-bindings/src/bindings.context.ts: -------------------------------------------------------------------------------- 1 | import type { UserDetails } from '@repo/mcp-common/src/durable-objects/user_details.do' 2 | import type { WorkersBindingsMCP } from './bindings.app' 3 | 4 | export interface Env { 5 | OAUTH_KV: KVNamespace 6 | ENVIRONMENT: 'development' | 'staging' | 'production' | 'test' 7 | MCP_SERVER_NAME: string 8 | MCP_SERVER_VERSION: string 9 | CLOUDFLARE_CLIENT_ID: string 10 | CLOUDFLARE_CLIENT_SECRET: string 11 | MCP_OBJECT: DurableObjectNamespace 12 | USER_DETAILS: DurableObjectNamespace 13 | MCP_METRICS: AnalyticsEngineDataset 14 | CLOUDFLARE_API_TOKEN: string 15 | OPENAI_API_KEY: string 16 | AI_GATEWAY_TOKEN: string 17 | CLOUDFLARE_ACCOUNT_ID: string 18 | AI_GATEWAY_ID: string 19 | AI: Ai 20 | VECTORIZE: VectorizeIndex 21 | DEV_DISABLE_OAUTH: string 22 | DEV_CLOUDFLARE_API_TOKEN: string 23 | DEV_CLOUDFLARE_EMAIL: string 24 | } 25 | -------------------------------------------------------------------------------- /apps/workers-bindings/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.evals.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/workers-bindings/vitest.config.evals.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | export default defineWorkersConfig({ 4 | test: { 5 | include: ['**/*.eval.?(c|m)[jt]s?(x)'], 6 | poolOptions: { 7 | workers: { 8 | isolatedStorage: true, 9 | wrangler: { configPath: './wrangler.jsonc' }, 10 | miniflare: { 11 | bindings: { 12 | ENVIRONMENT: 'test', 13 | }, 14 | }, 15 | }, 16 | }, 17 | }, 18 | }) 19 | -------------------------------------------------------------------------------- /apps/workers-bindings/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/bindings.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /apps/workers-builds/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | # OR 4 | DEV_DISABLE_OAUTH= 5 | DEV_CLOUDFLARE_API_TOKEN= 6 | DEV_CLOUDFLARE_EMAIL= 7 | -------------------------------------------------------------------------------- /apps/workers-builds/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/workers-builds/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # workers-builds 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | - @repo/mcp-common@0.19.1 11 | 12 | ## 0.1.3 13 | 14 | ### Patch Changes 15 | 16 | - cc6d41f: Update agents deps & modelcontextprotocol 17 | - Updated dependencies [1833c6d] 18 | - Updated dependencies [cc6d41f] 19 | - @repo/mcp-common@0.19.0 20 | - @repo/mcp-observability@0.32.1 21 | 22 | ## 0.1.2 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [f885d07] 27 | - @repo/mcp-common@0.18.0 28 | 29 | ## 0.1.1 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [83e2d19] 34 | - @repo/mcp-common@0.17.1 35 | 36 | ## 0.1.0 37 | 38 | ### Minor Changes 39 | 40 | - 6cf52a6: Support AOT tokens 41 | 42 | ### Patch Changes 43 | 44 | - 0fc4439: Update agents and modelcontext dependencies 45 | - Updated dependencies [6cf52a6] 46 | - Updated dependencies [0fc4439] 47 | - @repo/mcp-observability@0.32.0 48 | - @repo/mcp-common@0.17.0 49 | 50 | ## 0.0.4 51 | 52 | ### Patch Changes 53 | 54 | - 3677a18: Remove extraneous log 55 | - Updated dependencies [3677a18] 56 | - @repo/mcp-common@0.16.3 57 | 58 | ## 0.0.3 59 | 60 | ### Patch Changes 61 | 62 | - 86c2e4f: Add API token passthrough auth 63 | - Updated dependencies [86c2e4f] 64 | - @repo/mcp-common@0.16.2 65 | 66 | ## 0.0.2 67 | 68 | ### Patch Changes 69 | 70 | - cf3771b: chore: add suffixes to common files in apps and packages 71 | 72 | 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. 73 | 74 | - Updated dependencies [cf3771b] 75 | - @repo/mcp-common@0.16.1 76 | - @repo/mcp-observability@0.31.1 77 | -------------------------------------------------------------------------------- /apps/workers-builds/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | If you'd like to iterate and test your MCP server, you can do so in local development. 4 | 5 | ## Local Development 6 | 7 | 1. Create a `.dev.vars` file in your project root: 8 | 9 | If you're a Cloudflare employee: 10 | 11 | ``` 12 | CLOUDFLARE_CLIENT_ID=your_development_cloudflare_client_id 13 | CLOUDFLARE_CLIENT_SECRET=your_development_cloudflare_client_secret 14 | ``` 15 | 16 | If you're an external contributor, you can provide a development API token: 17 | 18 | ``` 19 | DEV_DISABLE_OAUTH=true 20 | DEV_CLOUDFLARE_EMAIL=your_cloudflare_email 21 | # This is your global api token 22 | DEV_CLOUDFLARE_API_TOKEN=your_development_api_token 23 | ``` 24 | 25 | 2. Start the local development server: 26 | 27 | ```bash 28 | pnpm dev 29 | ``` 30 | 31 | 3. To test locally, open Inspector, and connect to `http://localhost:8976/sse`. 32 | Once you follow the prompts, you'll be able to "List Tools". You can also connect with any MCP client. 33 | 34 | ## Deploying the Worker ( Cloudflare employees only ) 35 | 36 | Set secrets via Wrangler: 37 | 38 | ```bash 39 | npx wrangler secret put CLOUDFLARE_CLIENT_ID -e 40 | npx wrangler secret put CLOUDFLARE_CLIENT_SECRET -e 41 | ``` 42 | 43 | ## Set up a KV namespace 44 | 45 | Create the KV namespace: 46 | 47 | ```bash 48 | npx wrangler kv namespace create "OAUTH_KV" 49 | ``` 50 | 51 | Then, update the Wrangler file with the generated KV namespace ID. 52 | 53 | ## Deploy & Test 54 | 55 | Deploy the MCP server to make it available on your workers.dev domain: 56 | 57 | ```bash 58 | npx wrangler deploy -e 59 | ``` 60 | 61 | Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector): 62 | 63 | ```bash 64 | npx @modelcontextprotocol/inspector@latest 65 | ``` 66 | -------------------------------------------------------------------------------- /apps/workers-builds/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "workers-builds", 3 | "version": "0.1.4", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "wrangler deploy", 9 | "dev": "vite dev", 10 | "start": "vite dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-common": "workspace:*", 19 | "@repo/mcp-observability": "workspace:*", 20 | "agents": "0.0.100", 21 | "cloudflare": "4.2.0", 22 | "hono": "4.7.6", 23 | "zod": "3.24.2" 24 | }, 25 | "devDependencies": { 26 | "@cloudflare/vite-plugin": "1.1.0", 27 | "@cloudflare/vitest-pool-workers": "0.8.14", 28 | "@types/node": "22.14.1", 29 | "prettier": "3.5.3", 30 | "typescript": "5.5.4", 31 | "vite": "6.3.4", 32 | "vitest": "3.0.9", 33 | "wrangler": "4.10.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /apps/workers-builds/src/workers-builds.context.ts: -------------------------------------------------------------------------------- 1 | import type { UserDetails } from '@repo/mcp-common/src/durable-objects/user_details.do' 2 | import type { BuildsMCP } from './workers-builds.app' 3 | 4 | export interface Env { 5 | OAUTH_KV: KVNamespace 6 | ENVIRONMENT: 'development' | 'staging' | 'production' 7 | MCP_SERVER_NAME: string 8 | MCP_SERVER_VERSION: string 9 | CLOUDFLARE_CLIENT_ID: string 10 | CLOUDFLARE_CLIENT_SECRET: string 11 | MCP_OBJECT: DurableObjectNamespace 12 | USER_DETAILS: DurableObjectNamespace 13 | MCP_METRICS: AnalyticsEngineDataset 14 | SENTRY_ACCESS_CLIENT_ID: string 15 | SENTRY_ACCESS_CLIENT_SECRET: string 16 | GIT_HASH: string 17 | SENTRY_DSN: string 18 | DEV_DISABLE_OAUTH: string 19 | DEV_CLOUDFLARE_API_TOKEN: string 20 | DEV_CLOUDFLARE_EMAIL: string 21 | } 22 | -------------------------------------------------------------------------------- /apps/workers-builds/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.ts", "./types.d.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/workers-builds/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/workers-builds/vite.config.mts: -------------------------------------------------------------------------------- 1 | import { cloudflare } from '@cloudflare/vite-plugin' 2 | import { defineConfig } from 'vite' 3 | 4 | export default defineConfig({ 5 | plugins: [cloudflare()], 6 | server: { 7 | port: 8976, 8 | }, 9 | }) 10 | -------------------------------------------------------------------------------- /apps/workers-builds/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/workers-builds.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /apps/workers-observability/.dev.vars.example: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_CLIENT_ID= 2 | CLOUDFLARE_CLIENT_SECRET= 3 | DEV_DISABLE_OAUTH= 4 | DEV_CLOUDFLARE_API_TOKEN= 5 | DEV_CLOUDFLARE_EMAIL= -------------------------------------------------------------------------------- /apps/workers-observability/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /apps/workers-observability/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | If you'd like to iterate and test your MCP server, you can do so in local development. 4 | 5 | ## Local Development 6 | 7 | 1. Create a `.dev.vars` file in your project root: 8 | 9 | If you're a Cloudflare employee: 10 | 11 | ``` 12 | CLOUDFLARE_CLIENT_ID=your_development_cloudflare_client_id 13 | CLOUDFLARE_CLIENT_SECRET=your_development_cloudflare_client_secret 14 | ``` 15 | 16 | If you're an external contributor, you can provide a development API token: 17 | 18 | ``` 19 | DEV_DISABLE_OAUTH=true 20 | DEV_CLOUDFLARE_EMAIL=your_cloudflare_email 21 | # This is your global api token 22 | DEV_CLOUDFLARE_API_TOKEN=your_development_api_token 23 | ``` 24 | 25 | 2. Start the local development server: 26 | 27 | ```bash 28 | npx wrangler dev 29 | ``` 30 | 31 | 3. To test locally, open Inspector, and connect to `http://localhost:8976/sse`. 32 | Once you follow the prompts, you'll be able to "List Tools". You can also connect with any MCP client. 33 | 34 | ## Deploying the Worker ( Cloudflare employees only ) 35 | 36 | Set secrets via Wrangler: 37 | 38 | ```bash 39 | npx wrangler secret put CLOUDFLARE_CLIENT_ID -e 40 | npx wrangler secret put CLOUDFLARE_CLIENT_SECRET -e 41 | ``` 42 | 43 | ## Set up a KV namespace 44 | 45 | Create the KV namespace: 46 | 47 | ```bash 48 | npx wrangler kv namespace create "OAUTH_KV" 49 | ``` 50 | 51 | Then, update the Wrangler file with the generated KV namespace ID. 52 | 53 | ## Deploy & Test 54 | 55 | Deploy the MCP server to make it available on your workers.dev domain: 56 | 57 | ```bash 58 | npx wrangler deploy -e 59 | ``` 60 | 61 | Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector): 62 | 63 | ```bash 64 | npx @modelcontextprotocol/inspector@latest 65 | ``` 66 | -------------------------------------------------------------------------------- /apps/workers-observability/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "workers-observability", 3 | "version": "0.3.2", 4 | "private": true, 5 | "scripts": { 6 | "check:lint": "run-eslint-workers", 7 | "check:types": "run-tsc", 8 | "deploy": "wrangler deploy", 9 | "dev": "wrangler dev", 10 | "start": "wrangler dev", 11 | "types": "wrangler types --include-env=false", 12 | "test": "vitest run" 13 | }, 14 | "dependencies": { 15 | "@cloudflare/workers-oauth-provider": "0.0.5", 16 | "@fast-csv/format": "5.0.2", 17 | "@hono/zod-validator": "0.4.3", 18 | "@modelcontextprotocol/sdk": "1.13.3", 19 | "@repo/mcp-common": "workspace:*", 20 | "@repo/mcp-observability": "workspace:*", 21 | "agents": "0.0.100", 22 | "cloudflare": "4.2.0", 23 | "hono": "4.7.6", 24 | "zod": "3.24.2" 25 | }, 26 | "devDependencies": { 27 | "@cloudflare/vitest-pool-workers": "0.8.14", 28 | "@types/node": "22.14.1", 29 | "prettier": "3.5.3", 30 | "typescript": "5.5.4", 31 | "vitest": "3.0.9", 32 | "wrangler": "4.10.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /apps/workers-observability/src/workers-observability.context.ts: -------------------------------------------------------------------------------- 1 | import type { UserDetails } from '@repo/mcp-common/src/durable-objects/user_details.do' 2 | import type { ObservabilityMCP } from './workers-observability.app' 3 | 4 | export interface Env { 5 | OAUTH_KV: KVNamespace 6 | ENVIRONMENT: 'development' | 'staging' | 'production' 7 | MCP_SERVER_NAME: string 8 | MCP_SERVER_VERSION: string 9 | CLOUDFLARE_CLIENT_ID: string 10 | CLOUDFLARE_CLIENT_SECRET: string 11 | MCP_OBJECT: DurableObjectNamespace 12 | USER_DETAILS: DurableObjectNamespace 13 | MCP_METRICS: AnalyticsEngineDataset 14 | SENTRY_ACCESS_CLIENT_ID: string 15 | SENTRY_ACCESS_CLIENT_SECRET: string 16 | GIT_HASH: string 17 | SENTRY_DSN: string 18 | AI: Ai 19 | VECTORIZE: VectorizeIndex 20 | DEV_DISABLE_OAUTH: string 21 | DEV_CLOUDFLARE_API_TOKEN: string 22 | DEV_CLOUDFLARE_EMAIL: string 23 | } 24 | -------------------------------------------------------------------------------- /apps/workers-observability/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["*/**.ts", "./vitest.config.ts", "./types.d.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/workers-observability/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/workers-observability/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | import type { Env } from './src/workers-observability.context' 4 | 5 | export interface TestEnv extends Env { 6 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 7 | CLOUDFLARE_MOCK_API_TOKEN: string 8 | } 9 | 10 | export default defineWorkersConfig({ 11 | test: { 12 | poolOptions: { 13 | workers: { 14 | wrangler: { configPath: `${__dirname}/wrangler.jsonc` }, 15 | miniflare: { 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cloudflare/mcp-server-cloudflare", 3 | "version": "1.0.0", 4 | "description": "Monorepo for Cloudflare MCP servers", 5 | "private": true, 6 | "license": "Apache-2.0", 7 | "author": "Cloudflare, Inc. (https://cloudflare.com)", 8 | "homepage": "https://github.com/cloudflare/mcp-server-cloudflare", 9 | "bugs": "https://github.com/cloudflare/mcp-server-cloudflare/issues", 10 | "type": "module", 11 | "sideEffects": false, 12 | "scripts": { 13 | "changeset:new": "run-changeset-new", 14 | "check:deps": "syncpack lint", 15 | "check:format": "prettier . --check --cache --ignore-unknown", 16 | "check:turbo": "run-turbo check", 17 | "types": "run-turbo types", 18 | "test:ci": "run-vitest-ci", 19 | "test": "vitest run --passWithNoTests", 20 | "fix:format": "prettier . --write --cache --ignore-unknown", 21 | "fix:deps": "run-fix-deps", 22 | "test:watch": "vitest", 23 | "eval:ci": "run-turbo eval:ci", 24 | "eval:dev": "run-turbo eval:dev", 25 | "update-deps": "syncpack update" 26 | }, 27 | "devDependencies": { 28 | "@changesets/cli": "2.28.1", 29 | "@cloudflare/vitest-pool-workers": "0.8.14", 30 | "@ianvs/prettier-plugin-sort-imports": "4.4.1", 31 | "@repo/eslint-config": "workspace:*", 32 | "@repo/tools": "workspace:*", 33 | "@repo/typescript-config": "workspace:*", 34 | "@vitest/ui": "3.0.9", 35 | "prettier": "3.5.3", 36 | "syncpack": "13.0.3", 37 | "turbo": "2.5.0", 38 | "typescript": "5.5.4", 39 | "vitest": "3.0.9" 40 | }, 41 | "packageManager": "pnpm@10.8.0", 42 | "pnpm": { 43 | "onlyBuiltDependencies": [ 44 | "esbuild", 45 | "sharp", 46 | "workerd" 47 | ], 48 | "overrides": { 49 | "esbuild": "0.25.1" 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/eslint-config/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @repo/eslint-config 2 | 3 | ## 0.1.36 4 | 5 | ### Patch Changes 6 | 7 | - cc6d41f: Update agents deps & modelcontextprotocol 8 | -------------------------------------------------------------------------------- /packages/eslint-config/README.md: -------------------------------------------------------------------------------- 1 | # `@repo/eslint-config` 2 | 3 | Collection of internal eslint configurations. 4 | -------------------------------------------------------------------------------- /packages/eslint-config/default.cjs: -------------------------------------------------------------------------------- 1 | const { resolve } = require('node:path') 2 | 3 | const project = resolve(process.cwd(), 'tsconfig.json') 4 | 5 | /** @type {import("eslint").Linter.Config} */ 6 | module.exports = { 7 | ignorePatterns: ['.*.{js,cjs}', '**/node_modules/**', '**/dist/**', '**/dist2/**'], 8 | plugins: ['@typescript-eslint', 'import', 'unused-imports'], 9 | extends: ['turbo'], 10 | settings: { 11 | 'import/resolver': { 12 | typescript: { 13 | project, 14 | }, 15 | }, 16 | }, 17 | overrides: [ 18 | // TypeScript 19 | { 20 | // enable the rule specifically for TypeScript files 21 | files: ['**/*.{ts,tsx,mjs}'], 22 | parser: '@typescript-eslint/parser', 23 | parserOptions: { 24 | ecmaVersion: 2024, 25 | sourceType: 'module', 26 | project: true, 27 | }, 28 | extends: [ 29 | 'eslint:recommended', 30 | 'plugin:@typescript-eslint/recommended', 31 | 'plugin:import/typescript', 32 | 'turbo', 33 | 'prettier', // disable rules that conflict with prettier 34 | ], 35 | rules: { 36 | '@typescript-eslint/consistent-type-imports': ['warn', { prefer: 'type-imports' }], 37 | '@typescript-eslint/explicit-function-return-type': 'off', 38 | 'react-hooks/rules-of-hooks': 'off', 39 | '@typescript-eslint/ban-ts-comment': 'off', 40 | '@typescript-eslint/no-floating-promises': 'warn', 41 | 'unused-imports/no-unused-imports': 'warn', 42 | '@typescript-eslint/array-type': ['warn', { default: 'array-simple' }], 43 | '@typescript-eslint/no-unused-vars': [ 44 | 'warn', 45 | { 46 | argsIgnorePattern: '^_', 47 | varsIgnorePattern: '^_', 48 | caughtErrorsIgnorePattern: '^_', 49 | }, 50 | ], 51 | '@typescript-eslint/no-explicit-any': 'off', 52 | 'prefer-const': 'warn', 53 | 'no-mixed-spaces-and-tabs': ['error', 'smart-tabs'], 54 | 'no-empty': 'warn', 55 | }, 56 | }, 57 | 58 | // Node 59 | { 60 | files: ['.eslintrc.cjs'], 61 | env: { 62 | node: true, 63 | }, 64 | }, 65 | ], 66 | } 67 | -------------------------------------------------------------------------------- /packages/eslint-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/eslint-config", 3 | "version": "0.1.36", 4 | "private": true, 5 | "sideEffects": false, 6 | "files": [ 7 | "remix.cjs", 8 | "default.cjs" 9 | ], 10 | "devDependencies": { 11 | "@types/eslint": "8.56.10", 12 | "@types/node": "22.14.1", 13 | "@typescript-eslint/eslint-plugin": "7.18.0", 14 | "@typescript-eslint/parser": "7.18.0", 15 | "eslint": "8.57.0", 16 | "eslint-config-prettier": "9.1.0", 17 | "eslint-config-turbo": "2.4.2", 18 | "eslint-import-resolver-typescript": "3.8.3", 19 | "eslint-plugin-import": "2.31.0", 20 | "eslint-plugin-only-warn": "1.1.0", 21 | "eslint-plugin-unused-imports": "3.2.0", 22 | "typescript": "5.5.4", 23 | "vitest": "3.0.9" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/eval-tools/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @repo/eval-tools 2 | 3 | ## 0.32.1 4 | 5 | ### Patch Changes 6 | 7 | - cc6d41f: Update agents deps & modelcontextprotocol 8 | 9 | ## 0.32.0 10 | 11 | ### Minor Changes 12 | 13 | - 6cf52a6: Support AOT tokens 14 | 15 | ### Patch Changes 16 | 17 | - 0fc4439: Update agents and modelcontext dependencies 18 | -------------------------------------------------------------------------------- /packages/eval-tools/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/eval-tools", 3 | "version": "0.32.1", 4 | "private": true, 5 | "sideEffects": false, 6 | "type": "module", 7 | "scripts": { 8 | "types": "wrangler types --include-env=false" 9 | }, 10 | "directories": { 11 | "bin": "bin" 12 | }, 13 | "dependencies": { 14 | "@ai-sdk/anthropic": "1.2.11", 15 | "@ai-sdk/google": "1.2.17", 16 | "@ai-sdk/openai": "1.3.20", 17 | "@cloudflare/vitest-pool-workers": "0.8.14", 18 | "agents": "0.0.100", 19 | "ai": "4.3.10", 20 | "ai-gateway-provider": "0.0.6", 21 | "workers-ai-provider": "0.3.0", 22 | "wrangler": "4.10.0", 23 | "zod": "3.24.2" 24 | }, 25 | "devDependencies": { 26 | "@repo/typescript-config": "workspace:*", 27 | "@types/node": "22.14.1", 28 | "vitest-evals": "0.1.4" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/eval-tools/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["**/*.ts", "./worker-configuration.d.ts"], 4 | "exclude": ["node_modules", "tsconfig.json"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/eval-tools/wrangler.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stub-worker", 3 | "compatibility_date": "2025-04-14", 4 | "vars": { 5 | "OPENAI_API_KEY": "TODO", 6 | "AI_GATEWAY_TOKEN": "TODO", 7 | "CLOUDFLARE_ACCOUNT_ID": "TODO", 8 | "AI_GATEWAY_ID": "TODO" 9 | }, 10 | "ai": { 11 | "binding": "AI" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/mcp-common/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /packages/mcp-common/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @repo/mcp-common 2 | 3 | ## 0.19.1 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | - Updated dependencies [7422e71] 9 | - @repo/mcp-observability@0.32.2 10 | 11 | ## 0.19.0 12 | 13 | ### Minor Changes 14 | 15 | - 1833c6d: add relative timeframe support for querying 16 | 17 | ### Patch Changes 18 | 19 | - cc6d41f: Update agents deps & modelcontextprotocol 20 | - Updated dependencies [cc6d41f] 21 | - @repo/mcp-observability@0.32.1 22 | 23 | ## 0.18.0 24 | 25 | ### Minor Changes 26 | 27 | - f885d07: Add search docs tool to bindings and obs servers 28 | 29 | ## 0.17.1 30 | 31 | ### Patch Changes 32 | 33 | - 83e2d19: Pass in type user_token in props during oauth flow 34 | 35 | ## 0.17.0 36 | 37 | ### Minor Changes 38 | 39 | - 6cf52a6: Support AOT tokens 40 | 41 | ### Patch Changes 42 | 43 | - 0fc4439: Update agents and modelcontext dependencies 44 | - Updated dependencies [6cf52a6] 45 | - Updated dependencies [0fc4439] 46 | - @repo/mcp-observability@0.32.0 47 | 48 | ## 0.16.3 49 | 50 | ### Patch Changes 51 | 52 | - 3677a18: Remove extraneous log 53 | 54 | ## 0.16.2 55 | 56 | ### Patch Changes 57 | 58 | - 86c2e4f: Add API token passthrough auth 59 | 60 | ## 0.16.1 61 | 62 | ### Patch Changes 63 | 64 | - cf3771b: chore: add suffixes to common files in apps and packages 65 | 66 | 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. 67 | 68 | - @repo/mcp-observability@0.31.1 69 | -------------------------------------------------------------------------------- /packages/mcp-common/README.md: -------------------------------------------------------------------------------- 1 | # MCP Common 2 | 3 | A place for common things used across MCP packages/apps 4 | -------------------------------------------------------------------------------- /packages/mcp-common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/mcp-common", 3 | "version": "0.19.1", 4 | "private": true, 5 | "sideEffects": false, 6 | "main": "./src/index.ts", 7 | "scripts": { 8 | "check:lint": "run-eslint-workers", 9 | "check:types": "run-tsc", 10 | "test": "vitest run", 11 | "test:coverage": "run-vitest-coverage" 12 | }, 13 | "dependencies": { 14 | "@cloudflare/workers-oauth-provider": "0.0.5", 15 | "@fast-csv/format": "5.0.2", 16 | "@hono/zod-validator": "0.4.3", 17 | "@modelcontextprotocol/sdk": "1.13.3", 18 | "@repo/mcp-observability": "workspace:*", 19 | "agents": "0.0.100", 20 | "cloudflare": "4.2.0", 21 | "hono": "4.7.6", 22 | "toucan-js": "4.1.1", 23 | "zod": "3.24.2" 24 | }, 25 | "devDependencies": { 26 | "@cloudflare/vitest-pool-workers": "0.8.14", 27 | "@repo/eslint-config": "workspace:*", 28 | "@repo/tools": "workspace:*", 29 | "@repo/typescript-config": "workspace:*", 30 | "@sentry/types": "8.9.2", 31 | "@types/node": "22.14.1", 32 | "@vitest/ui": "3.0.9", 33 | "vitest": "3.0.9", 34 | "wrangler": "4.10.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/mcp-common/src/api-handler.ts: -------------------------------------------------------------------------------- 1 | import type { McpAgent } from 'agents/mcp' 2 | 3 | // Support both SSE and Streamable HTTP 4 | export function createApiHandler< 5 | T extends typeof McpAgent>, 6 | >(agent: T, opts?: { binding?: string }) { 7 | return { 8 | fetch: (req: Request, env: unknown, ctx: ExecutionContext) => { 9 | const url = new URL(req.url) 10 | if (url.pathname === '/sse' || url.pathname === '/sse/message') { 11 | return agent.serveSSE('/sse', { binding: opts?.binding }).fetch(req, env, ctx) 12 | } 13 | if (url.pathname === '/mcp') { 14 | return agent.serve('/mcp', { binding: opts?.binding }).fetch(req, env, ctx) 15 | } 16 | return new Response('Not found', { status: 404 }) 17 | }, 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/mcp-common/src/api/account.api.ts: -------------------------------------------------------------------------------- 1 | import type { Cloudflare } from 'cloudflare' 2 | import type { Account } from 'cloudflare/resources/accounts/accounts.mjs' 3 | import type { CloudflareMcpAgent } from '../types/cloudflare-mcp-agent.types' 4 | import type { ToolHandler } from '../types/tools.types' 5 | 6 | export async function handleAccountsList({ client }: { client: Cloudflare }): Promise { 7 | // Currently limited to 50 accounts 8 | const response = await client.accounts.list({ query: { per_page: 50 } }) 9 | return response.result 10 | } 11 | 12 | export const withAccountCheck = >( 13 | agent: CloudflareMcpAgent, 14 | handler: ToolHandler 15 | ) => { 16 | return async (params: T) => { 17 | const accountId = await agent.getActiveAccountId() 18 | if (!accountId) { 19 | return { 20 | content: [ 21 | { 22 | type: 'text' as const, 23 | text: 'No currently active accountId. Try listing your accounts (accounts_list) and then setting an active account (set_active_account)', 24 | }, 25 | ], 26 | } 27 | } 28 | 29 | try { 30 | const result = await handler({ 31 | ...params, 32 | accountId, 33 | apiToken: agent.props.accessToken || '', 34 | }) 35 | return { 36 | content: [{ type: 'text' as const, text: JSON.stringify(result) }], 37 | } 38 | } catch (error) { 39 | return { 40 | content: [ 41 | { 42 | type: 'text' as const, 43 | text: JSON.stringify({ 44 | error: `Error processing request: ${error instanceof Error ? error.message : 'Unknown error'}`, 45 | }), 46 | }, 47 | ], 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/mcp-common/src/api/workers-builds.api.ts: -------------------------------------------------------------------------------- 1 | import { fetchCloudflareApi } from '../cloudflare-api' 2 | import { 3 | GetBuildLogsResult, 4 | GetBuildResult, 5 | ListBuildsByScriptResult, 6 | ListBuildsByScriptResultInfo, 7 | } from '../types/workers-builds.types' 8 | import { V4Schema } from '../v4-api' 9 | 10 | import type { LogLine } from '../types/workers-builds.types' 11 | 12 | export async function listBuilds({ 13 | accountId, 14 | workerId, 15 | page = 1, 16 | perPage = 10, 17 | apiToken, 18 | }: { 19 | accountId: string 20 | workerId: string 21 | page?: number 22 | perPage?: number 23 | apiToken: string 24 | }) { 25 | return fetchCloudflareApi({ 26 | endpoint: `/builds/workers/${workerId}/builds?page=${page}&per_page=${perPage}`, 27 | accountId, 28 | apiToken, 29 | responseSchema: V4Schema(ListBuildsByScriptResult, ListBuildsByScriptResultInfo), 30 | }) 31 | } 32 | 33 | export async function getBuild({ 34 | accountId, 35 | buildUUID, 36 | apiToken, 37 | }: { 38 | accountId: string 39 | buildUUID: string 40 | apiToken: string 41 | }) { 42 | return fetchCloudflareApi({ 43 | endpoint: `/builds/builds/${buildUUID}`, 44 | accountId, 45 | apiToken, 46 | responseSchema: V4Schema(GetBuildResult), 47 | }) 48 | } 49 | 50 | export async function getBuildLogs({ 51 | accountId, 52 | buildUUID, 53 | apiToken, 54 | }: { 55 | accountId: string 56 | buildUUID: string 57 | apiToken: string 58 | }) { 59 | const allLogs: LogLine[] = [] 60 | let cursor: string | undefined = undefined 61 | let hasMore = true 62 | 63 | while (hasMore) { 64 | let endpoint = `/builds/builds/${buildUUID}/logs` 65 | if (cursor) { 66 | endpoint += `?cursor=${cursor}` 67 | } 68 | 69 | const res = await fetchCloudflareApi({ 70 | endpoint, 71 | accountId, 72 | apiToken, 73 | responseSchema: V4Schema(GetBuildLogsResult), 74 | }) 75 | 76 | if (res.result) { 77 | allLogs.push(...res.result.lines) 78 | 79 | if (res.result.cursor && res.result.truncated) { 80 | cursor = res.result.cursor 81 | } else { 82 | hasMore = false 83 | } 84 | } 85 | } 86 | 87 | return allLogs 88 | } 89 | -------------------------------------------------------------------------------- /packages/mcp-common/src/api/workers.api.ts: -------------------------------------------------------------------------------- 1 | import { fetchCloudflareApi } from '../cloudflare-api' 2 | import { WorkersService } from '../types/workers.types' 3 | import { V4Schema } from '../v4-api' 4 | 5 | import type { Cloudflare } from 'cloudflare' 6 | 7 | /** 8 | * Fetches list of workers from Cloudflare API 9 | * @param client Cloudflare API Client 10 | * @param accountId Cloudflare account ID 11 | * @returns List of workers 12 | */ 13 | export async function handleWorkersList({ 14 | client, 15 | accountId, 16 | }: { 17 | client: Cloudflare 18 | accountId: string 19 | }): Promise { 20 | return (await client.workers.scripts.list({ account_id: accountId })).result 21 | } 22 | 23 | /** 24 | * Get details of a worker script from Cloudflare API 25 | * @param client Cloudflare API Client 26 | * @param scriptName Name of the worker script to download 27 | * @param accountId Cloudflare account ID 28 | * @returns The script name and id 29 | */ 30 | export async function handleGetWorkersService({ 31 | apiToken, 32 | scriptName, 33 | accountId, 34 | }: { 35 | apiToken: string 36 | scriptName: string 37 | accountId: string 38 | }) { 39 | return await fetchCloudflareApi({ 40 | endpoint: `/workers/services/${scriptName}`, 41 | accountId, 42 | apiToken, 43 | responseSchema: V4Schema(WorkersService), 44 | }) 45 | } 46 | 47 | /** 48 | * Downloads a specific worker script from Cloudflare API 49 | * @param client Cloudflare API Client 50 | * @param scriptName Name of the worker script to download 51 | * @param accountId Cloudflare account ID 52 | * @returns The worker script content 53 | */ 54 | export async function handleWorkerScriptDownload({ 55 | client, 56 | scriptName, 57 | accountId, 58 | }: { 59 | client: Cloudflare 60 | scriptName: string 61 | accountId: string 62 | }): Promise { 63 | return await client.workers.scripts.get(scriptName, { account_id: accountId }) 64 | } 65 | -------------------------------------------------------------------------------- /packages/mcp-common/src/api/zone.api.ts: -------------------------------------------------------------------------------- 1 | import type { Cloudflare } from 'cloudflare' 2 | 3 | export interface ZoneListParams { 4 | client: Cloudflare 5 | accountId: string 6 | page?: number 7 | perPage?: number 8 | direction?: 'asc' | 'desc' 9 | match?: 'any' | 'all' 10 | name?: string 11 | status?: string 12 | order?: string 13 | } 14 | 15 | /** 16 | * Lists zones under a Cloudflare account 17 | * @see https://developers.cloudflare.com/api/resources/zones/methods/list/ 18 | */ 19 | export async function handleZonesList({ 20 | client, 21 | accountId, 22 | page = 1, 23 | perPage = 50, 24 | direction = 'desc', 25 | match = 'all', 26 | name, 27 | status, 28 | order = 'name', 29 | }: ZoneListParams) { 30 | // Build query parameters 31 | const query: Record = { 32 | page, 33 | per_page: perPage, 34 | direction, 35 | match, 36 | account_id: accountId, 37 | } 38 | 39 | // Only add these parameters if they're defined and not empty strings 40 | if (name) { 41 | query.name = name 42 | } 43 | 44 | if (status) { 45 | query.status = status 46 | } 47 | 48 | if (order) { 49 | query.order = order 50 | } 51 | 52 | try { 53 | // Use the zones.list method from the Cloudflare client 54 | const response = await client.zones.list({ query }) 55 | return response.result 56 | } catch (error) { 57 | throw new Error( 58 | `Failed to list zones: ${error instanceof Error ? error.message : String(error)}` 59 | ) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/mcp-common/src/config.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export type MCPEnvironment = z.infer 4 | export const MCPEnvironment = z.enum(['VITEST', 'development', 'staging', 'production']) 5 | 6 | export function getEnvironment(environment: string) { 7 | return MCPEnvironment.parse(environment) 8 | } 9 | -------------------------------------------------------------------------------- /packages/mcp-common/src/constants.ts: -------------------------------------------------------------------------------- 1 | import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js' 2 | 3 | export const MISSING_ACCOUNT_ID_RESPONSE = { 4 | content: [ 5 | { 6 | type: 'text', 7 | text: 'No currently active accountId. Try listing your accounts (accounts_list) and then setting an active account (set_active_account)', 8 | }, 9 | ], 10 | } satisfies CallToolResult 11 | -------------------------------------------------------------------------------- /packages/mcp-common/src/durable-objects/user_details.do.ts: -------------------------------------------------------------------------------- 1 | import { DurableObject } from 'cloudflare:workers' 2 | import { z } from 'zod' 3 | 4 | import { DurableKVStore } from '../durable-kv-store' 5 | 6 | import type { DurableKVStorageKeys } from '../durable-kv-store' 7 | 8 | // Durable Object for persisting UserDetails in DO storage across sessions based off the userId 9 | export class UserDetails extends DurableObject { 10 | private readonly kv: DurableKVStore 11 | constructor(state: DurableObjectState, env: unknown) { 12 | super(state, env) 13 | this.env = env 14 | this.kv = new DurableKVStore({ 15 | state, 16 | prefix: 'meta', 17 | keys: UserDetailsKeys, 18 | }) 19 | } 20 | 21 | public async getActiveAccountId() { 22 | return await this.kv.get('active_account_id') 23 | } 24 | 25 | public async setActiveAccountId(activeAccountId: string) { 26 | this.kv.put('active_account_id', activeAccountId) 27 | } 28 | } 29 | 30 | /** 31 | * Storage keys used by UserDetails 32 | */ 33 | type UserDetailsKeys = typeof UserDetailsKeys 34 | const UserDetailsKeys = { 35 | active_account_id: z.string(), 36 | } as const satisfies DurableKVStorageKeys 37 | 38 | /** Get the UserDetails instance */ 39 | export function getUserDetails( 40 | env: { USER_DETAILS: DurableObjectNamespace }, 41 | user_id: string 42 | ): DurableObjectStub { 43 | const id = env.USER_DETAILS.idFromName(user_id) 44 | return env.USER_DETAILS.get(id) 45 | } 46 | -------------------------------------------------------------------------------- /packages/mcp-common/src/env.ts: -------------------------------------------------------------------------------- 1 | import { env } from 'cloudflare:workers' 2 | 3 | // Helper to cast env as any generic Env type 4 | export function getEnv() { 5 | return env as Env 6 | } 7 | -------------------------------------------------------------------------------- /packages/mcp-common/src/format.ts: -------------------------------------------------------------------------------- 1 | import { writeToString } from '@fast-csv/format' 2 | 3 | /** 4 | * A collection of formatting functions (think of it like Golang's `fmt` package) 5 | */ 6 | export const fmt = { 7 | /** 8 | * Trims all lines of a string. 9 | * Useful for formatting tool instructions. 10 | */ 11 | trim: (str: string): string => 12 | str 13 | .trim() 14 | .split('\n') 15 | .map((line) => line.trim()) 16 | .join('\n'), 17 | 18 | /** 19 | * Converts a multi-line string into a single line. 20 | * Useful for formatting tool instructions. 21 | */ 22 | oneLine: (str: string): string => 23 | str 24 | .trim() 25 | .split('\n') 26 | .map((line) => line.trim()) 27 | .filter((line) => line.length > 0) 28 | .join(' '), 29 | 30 | /** 31 | * Convert an array of objects to a string of tab-separated values (TSV). 32 | * This is better than JSON for returning data to the model because it uses fewer tokens 33 | */ 34 | asTSV: (data: any[]): Promise => writeToString(data, { headers: true, delimiter: '\t' }), 35 | } as const 36 | -------------------------------------------------------------------------------- /packages/mcp-common/src/mcp-error.ts: -------------------------------------------------------------------------------- 1 | import type { ContentfulStatusCode } from 'hono/utils/http-status' 2 | 3 | export class McpError extends Error { 4 | public code: ContentfulStatusCode 5 | public reportToSentry: boolean 6 | // error message for internal use 7 | public internalMessage?: string 8 | public cause?: Error 9 | constructor( 10 | message: string, 11 | code: ContentfulStatusCode, 12 | opts: { 13 | reportToSentry: boolean 14 | internalMessage?: string 15 | cause?: Error 16 | } = { reportToSentry: false } 17 | ) { 18 | super(message) 19 | this.code = code 20 | this.name = 'MCPError' 21 | this.reportToSentry = opts.reportToSentry 22 | this.internalMessage = opts.internalMessage 23 | this.cause = opts.cause 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/mcp-common/src/poll.ts: -------------------------------------------------------------------------------- 1 | type PollOptions = { 2 | taskFn: () => Promise 3 | checkFn?: (result: T) => boolean 4 | intervalSeconds?: number 5 | maxWaitSeconds?: number 6 | onError?: (error: unknown) => void 7 | } 8 | 9 | const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) 10 | 11 | export async function pollUntilReady({ 12 | taskFn, 13 | checkFn = (result: T) => Boolean(result), 14 | intervalSeconds = 5, 15 | maxWaitSeconds = 60, 16 | onError = () => {}, 17 | }: PollOptions): Promise { 18 | let elapsed = 0 19 | let result: T | null = null 20 | 21 | while (elapsed < maxWaitSeconds) { 22 | try { 23 | result = await taskFn() 24 | if (checkFn(result)) break 25 | } catch (error) { 26 | onError(error) 27 | } 28 | 29 | await sleep(intervalSeconds * 1000) 30 | elapsed += intervalSeconds 31 | } 32 | 33 | if (result === null || !checkFn(result)) { 34 | throw new Error('Polling timed out or condition not met') 35 | } 36 | 37 | return result 38 | } 39 | -------------------------------------------------------------------------------- /packages/mcp-common/src/prompts/docs-vectorize.prompts.ts: -------------------------------------------------------------------------------- 1 | import type { CloudflareMcpAgentNoAccount } from '../types/cloudflare-mcp-agent.types' 2 | 3 | /** 4 | * Registers developer-platform-related prompts with the MCP server 5 | * @param agent The MCP server instance 6 | */ 7 | export function registerPrompts(agent: CloudflareMcpAgentNoAccount) { 8 | agent.server.prompt( 9 | 'workers-prompt-full', 10 | 'Detailed prompt for generating Cloudflare Workers code (and other developer platform products) from https://developers.cloudflare.com/workers/prompt.txt', 11 | async () => ({ 12 | messages: [ 13 | { 14 | role: 'user', 15 | content: { 16 | type: 'text', 17 | text: await ( 18 | await fetch('https://developers.cloudflare.com/workers/prompt.txt', { 19 | cf: { cacheEverything: true, cacheTtl: 3600 }, 20 | }) 21 | ).text(), 22 | }, 23 | }, 24 | ], 25 | }) 26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /packages/mcp-common/src/scopes.ts: -------------------------------------------------------------------------------- 1 | // These scopes are required for Cloudflare auth 2 | export const RequiredScopes = { 3 | 'user:read': 'See your user info such as name, email address, and account memberships.', 4 | offline_access: 'Grants refresh tokens for long-lived access.', 5 | } as const 6 | -------------------------------------------------------------------------------- /packages/mcp-common/src/types/cloudflare-mcp-agent.types.ts: -------------------------------------------------------------------------------- 1 | import { type McpAgent } from 'agents/mcp' 2 | 3 | import type { AuthProps } from '../cloudflare-oauth-handler' 4 | import type { CloudflareMCPServer } from '../server' 5 | 6 | export type CloudflareMCPAgentState = { activeAccountId: string | null } 7 | 8 | export type CloudflareMCPAgentProps = AuthProps 9 | 10 | // We omit server in this type, so that we can later use our own CloudflareMCPServer type ( which extends McpServer ) 11 | type McpAgentWithoutServer = Omit< 12 | McpAgent, 13 | 'server' 14 | > 15 | 16 | export interface CloudflareMcpAgentNoAccount 17 | extends McpAgentWithoutServer { 18 | server: CloudflareMCPServer 19 | } 20 | 21 | export interface CloudflareMcpAgent 22 | extends CloudflareMcpAgentNoAccount { 23 | setActiveAccountId(accountId: string): Promise 24 | getActiveAccountId(): Promise 25 | } 26 | -------------------------------------------------------------------------------- /packages/mcp-common/src/types/d1.types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file contains the validators for the d1 tools. 3 | */ 4 | import { z } from 'zod' 5 | 6 | import type { DatabaseCreateParams } from 'cloudflare/resources/d1.mjs' 7 | 8 | export const D1DatabaseNameParam: z.ZodType = z.string() 9 | export const D1DatabasePrimaryLocationHintParam: z.ZodType< 10 | DatabaseCreateParams['primary_location_hint'] 11 | > = z.enum(['wnam', 'enam', 'weur', 'eeur', 'apac', 'oc']).optional() 12 | 13 | export const D1DatabaseQuerySqlParam = z.string() 14 | export const D1DatabaseQueryParamsParam = z.array(z.string()).optional() 15 | -------------------------------------------------------------------------------- /packages/mcp-common/src/types/shared.types.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export const PaginationPerPageParam = z.number().nullable().optional() 4 | export const PaginationPageParam = z.number().nullable().optional() 5 | 6 | export const PaginationLimitParam = z.number().optional() 7 | export const PaginationOffsetParam = z.number().optional() 8 | -------------------------------------------------------------------------------- /packages/mcp-common/src/types/tools.types.ts: -------------------------------------------------------------------------------- 1 | import type { z } from 'zod' 2 | 3 | export type ToolHandler> = ( 4 | params: T & { accountId: string | null; apiToken: string } 5 | ) => Promise 6 | 7 | export interface ToolDefinition> { 8 | name: string 9 | description: string 10 | params: Record 11 | handler: ToolHandler 12 | } 13 | -------------------------------------------------------------------------------- /packages/mcp-common/src/types/workers.types.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export type WorkersService = z.infer 4 | export const WorkersService = z.object({ 5 | id: z.string(), 6 | default_environment: z.object({ 7 | environment: z.string(), 8 | script_tag: z.string(), 9 | created_on: z.string(), 10 | modified_on: z.string(), 11 | script: z.object({ 12 | created_on: z.string(), 13 | modified_on: z.string(), 14 | id: z.string(), 15 | }), 16 | }), 17 | created_on: z.string(), 18 | modified_on: z.string(), 19 | }) 20 | -------------------------------------------------------------------------------- /packages/mcp-common/src/utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | import { nowISO, parseRelativeTime } from './utils' 4 | 5 | describe('parseRelativeTime', () => { 6 | it('parses positive relative time correctly', () => { 7 | expect(parseRelativeTime('+1h')).toBe(3600) 8 | expect(parseRelativeTime('+2d')).toBe(172800) 9 | expect(parseRelativeTime('+3w')).toBe(1814400) 10 | }) 11 | 12 | it('parses negative relative time correctly', () => { 13 | expect(parseRelativeTime('-1h')).toBe(-3600) 14 | expect(parseRelativeTime('-2d')).toBe(-172800) 15 | expect(parseRelativeTime('-3w')).toBe(-1814400) 16 | }) 17 | 18 | it('parses mixed units correctly', () => { 19 | expect(parseRelativeTime('+1h30m')).toBe(5400) 20 | expect(parseRelativeTime('-2d6h')).toBe(-194400) 21 | }) 22 | 23 | it('throws an error for invalid formats', () => { 24 | expect(() => parseRelativeTime('1h')).toThrow() 25 | expect(() => parseRelativeTime('+')).toThrow() 26 | expect(() => parseRelativeTime('')).toThrow() 27 | }) 28 | }) 29 | 30 | describe('nowISO', () => { 31 | it('returns the current time in ISO format without milliseconds', () => { 32 | const isoRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/ 33 | expect(nowISO()).toMatch(isoRegex) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /packages/mcp-common/src/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Utility functions for common operations 3 | */ 4 | 5 | /** 6 | * Parse a relative time string into seconds 7 | */ 8 | export function parseRelativeTime(input: string): number { 9 | const units = { s: 1, m: 60, h: 3600, d: 86400, w: 604800 } as const 10 | 11 | const cleanedInput = input.replace(/\s+/g, '').toLowerCase() 12 | if (!/^[+-](?:\d+[smhdw]){1,}$/.test(cleanedInput)) { 13 | throw new Error(`Invalid relative time format: ${input}`) 14 | } 15 | 16 | const sign = cleanedInput.startsWith('-') ? -1 : 1 17 | 18 | const timeStr = cleanedInput.slice(1) // Remove the sign 19 | const matches = timeStr.match(/\d+[smhdw]/g) 20 | 21 | if (!matches) { 22 | throw new Error(`No matches found while parsing relative time: ${timeStr}`) 23 | } 24 | 25 | const seconds = matches.reduce((total, match) => { 26 | const value = parseInt(match) 27 | const unit = match.slice(-1) as keyof typeof units 28 | 29 | return total + value * units[unit] 30 | }, 0) 31 | 32 | return sign * seconds 33 | } 34 | 35 | /** 36 | * Get the current time as an ISO string without milliseconds 37 | */ 38 | export function nowISO(): string { 39 | return new Date().toISOString().split('.')[0] + 'Z' 40 | } 41 | -------------------------------------------------------------------------------- /packages/mcp-common/src/v4-api.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | type V4ErrorSchema = typeof V4ErrorSchema 4 | const V4ErrorSchema = z.array( 5 | z.object({ 6 | code: z.number().optional(), 7 | message: z.string(), 8 | }) 9 | ) 10 | 11 | export type V4Schema = z.ZodObject<{ 12 | result: z.ZodNullable 13 | success: z.ZodBoolean 14 | errors: V4ErrorSchema 15 | messages: z.ZodArray 16 | }> 17 | 18 | export type V4SchemaWithResultInfo< 19 | TResultType extends z.ZodType, 20 | TResultInfoType extends z.ZodType, 21 | > = z.ZodObject<{ 22 | result: z.ZodNullable 23 | success: z.ZodBoolean 24 | errors: V4ErrorSchema 25 | messages: z.ZodArray 26 | result_info: z.ZodOptional> 27 | }> 28 | 29 | export function V4Schema( 30 | resultType: TResultType 31 | ): V4Schema 32 | export function V4Schema( 33 | resultType: TResultType, 34 | resultInfoType: TResultInfoType 35 | ): V4SchemaWithResultInfo 36 | export function V4Schema( 37 | resultType: TResultType, 38 | resultInfoType?: TResultInfoType 39 | ): V4Schema | V4SchemaWithResultInfo { 40 | if (resultInfoType) { 41 | return z.object({ 42 | result: resultType.nullable(), 43 | result_info: resultInfoType.nullable().optional(), 44 | success: z.boolean(), 45 | errors: V4ErrorSchema, 46 | messages: z.array(z.any()), 47 | }) 48 | } else { 49 | return z.object({ 50 | result: resultType.nullable(), 51 | success: z.boolean(), 52 | errors: V4ErrorSchema, 53 | messages: z.array(z.any()), 54 | }) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/mcp-common/tests/utils/cloudflare-mock.ts: -------------------------------------------------------------------------------- 1 | import { vi } from 'vitest' 2 | 3 | import type { Account } from 'cloudflare/resources/accounts/accounts.mjs' 4 | 5 | /** 6 | * Creates a mocked implementation of the Cloudflare client 7 | */ 8 | export const cloudflareClientMockImplementation = () => { 9 | return { 10 | accounts: { 11 | list: vi.fn(async () => { 12 | return { 13 | success: true, 14 | result: [ 15 | { 16 | id: 'mock-account-id', 17 | name: 'mock-account-name', 18 | }, 19 | ] satisfies Account[], 20 | } 21 | }), 22 | }, 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/mcp-common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers-lib.json", 3 | "include": ["**/*.ts"], 4 | "exclude": ["node_modules", "tsconfig.json"], 5 | "compilerOptions": { 6 | "types": ["@cloudflare/vitest-pool-workers"] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/mcp-common/types.d.ts: -------------------------------------------------------------------------------- 1 | import type { TestEnv } from './vitest.config' 2 | 3 | declare module 'cloudflare:test' { 4 | interface ProvidedEnv extends TestEnv {} 5 | } 6 | -------------------------------------------------------------------------------- /packages/mcp-common/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersProject } from '@cloudflare/vitest-pool-workers/config' 2 | 3 | export interface TestEnv { 4 | CLOUDFLARE_MOCK_ACCOUNT_ID: string 5 | CLOUDFLARE_MOCK_API_TOKEN: string 6 | } 7 | 8 | export default defineWorkersProject({ 9 | test: { 10 | poolOptions: { 11 | workers: { 12 | singleWorker: true, 13 | miniflare: { 14 | compatibilityDate: '2025-03-10', 15 | compatibilityFlags: ['nodejs_compat'], 16 | bindings: { 17 | CLOUDFLARE_MOCK_ACCOUNT_ID: 'mock-account-id', 18 | CLOUDFLARE_MOCK_API_TOKEN: 'mock-api-token', 19 | } satisfies Partial, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /packages/mcp-observability/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @repo/mcp-observability 2 | 3 | ## 0.32.2 4 | 5 | ### Patch Changes 6 | 7 | - 7422e71: Update MCP sdk 8 | 9 | ## 0.32.1 10 | 11 | ### Patch Changes 12 | 13 | - cc6d41f: Update agents deps & modelcontextprotocol 14 | 15 | ## 0.32.0 16 | 17 | ### Minor Changes 18 | 19 | - 6cf52a6: Support AOT tokens 20 | 21 | ### Patch Changes 22 | 23 | - 0fc4439: Update agents and modelcontext dependencies 24 | -------------------------------------------------------------------------------- /packages/mcp-observability/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/mcp-observability", 3 | "version": "0.32.2", 4 | "private": true, 5 | "sideEffects": false, 6 | "type": "module", 7 | "main": "./src/index.ts", 8 | "scripts": { 9 | "types": "wrangler types --include-env=false" 10 | }, 11 | "directories": { 12 | "bin": "bin" 13 | }, 14 | "dependencies": { 15 | "@modelcontextprotocol/sdk": "1.13.3", 16 | "wrangler": "4.10.0", 17 | "zod": "3.24.2" 18 | }, 19 | "devDependencies": { 20 | "@repo/typescript-config": "workspace:*", 21 | "@types/node": "22.14.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/mcp-observability/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './analytics-engine' 2 | export * from './metrics' 3 | -------------------------------------------------------------------------------- /packages/mcp-observability/src/metrics.ts: -------------------------------------------------------------------------------- 1 | import { type ClientCapabilities } from '@modelcontextprotocol/sdk/types.js' 2 | 3 | import { MetricsEvent, MetricsEventIndexIds } from './analytics-engine' 4 | 5 | /** 6 | * TODO: once there are better hooks into MCP servers, we should track the session ID 7 | */ 8 | export class ToolCall extends MetricsEvent { 9 | constructor( 10 | private toolCall: { 11 | userId?: string 12 | toolName: string 13 | errorCode?: number 14 | } 15 | ) { 16 | super() 17 | } 18 | 19 | toDataPoint(): AnalyticsEngineDataPoint { 20 | return { 21 | indexes: [MetricsEventIndexIds.TOOL_CALL], 22 | blobs: this.mapBlobs({ 23 | blob3: this.toolCall.userId, 24 | blob4: this.toolCall.toolName, 25 | }), 26 | doubles: this.mapDoubles({ 27 | double1: this.toolCall.errorCode, 28 | }), 29 | } 30 | } 31 | } 32 | 33 | export class SessionStart extends MetricsEvent { 34 | constructor( 35 | private session: { 36 | userId?: string 37 | clientInfo?: { 38 | name: string 39 | version: string 40 | } 41 | clientCapabilities?: ClientCapabilities 42 | } 43 | ) { 44 | super() 45 | } 46 | 47 | toDataPoint(): AnalyticsEngineDataPoint { 48 | return { 49 | indexes: [MetricsEventIndexIds.SESSION_START], 50 | blobs: this.mapBlobs({ 51 | blob3: this.session.userId, 52 | blob4: this.session.clientInfo?.name, 53 | blob5: this.session.clientInfo?.version, 54 | }), 55 | doubles: this.mapDoubles({ 56 | double1: this.session.clientCapabilities?.roots ? 1 : 0, 57 | double2: this.session.clientCapabilities?.sampling ? 1 : 0, 58 | }), 59 | } 60 | } 61 | } 62 | 63 | export class AuthUser extends MetricsEvent { 64 | constructor( 65 | private authUser: { 66 | userId?: string 67 | errorMessage?: string 68 | } 69 | ) { 70 | super() 71 | } 72 | 73 | toDataPoint(): AnalyticsEngineDataPoint { 74 | return { 75 | indexes: [MetricsEventIndexIds.AUTH_USER], 76 | blobs: this.mapBlobs({ 77 | blob3: this.authUser.userId, 78 | blob4: this.authUser.errorMessage, 79 | }), 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /packages/mcp-observability/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/workers.json", 3 | "include": ["**/*.ts"], 4 | "exclude": ["node_modules", "tsconfig.json"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/tools/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ['@repo/eslint-config/default.cjs'], 5 | } 6 | -------------------------------------------------------------------------------- /packages/tools/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @repo/tools 2 | 3 | ## 0.33.1 4 | 5 | ### Patch Changes 6 | 7 | - cc6d41f: Update agents deps & modelcontextprotocol 8 | 9 | ## 0.33.0 10 | 11 | ### Minor Changes 12 | 13 | - 6cf52a6: Support AOT tokens 14 | 15 | ### Patch Changes 16 | 17 | - 0fc4439: Update agents and modelcontext dependencies 18 | 19 | ## 0.32.1 20 | 21 | ### Patch Changes 22 | 23 | - 86c2e4f: Add API token passthrough auth 24 | 25 | ## 0.32.0 26 | 27 | ### Minor Changes 28 | 29 | - 33e0198: BANDA-899 feat: add runx deploy-published-workers script 30 | 31 | ### Patch Changes 32 | 33 | - bdb5b89: chore: remove pnpx from wrangler deploy script 34 | 35 | This is redundant because turbo and pnpm already add the bundled wrangler command to $PATH 36 | -------------------------------------------------------------------------------- /packages/tools/README.md: -------------------------------------------------------------------------------- 1 | # @repo/tools 2 | 3 | A collection of shared scripts for automating the monorepo while ensuring consistency across packages. 4 | 5 | ## Scripts 6 | 7 | ### Bin Scripts 8 | 9 | Simple shell scripts for common development tasks: 10 | 11 | - `run-tsc`: Run TypeScript type checking 12 | - `run-eslint-workers`: Run ESLint checks 13 | - `run-vitest`: Run tests 14 | - `run-vitest-ci`: Run tests in CI mode 15 | - `run-turbo`: Run Turbo commands with tracking disabled 16 | - `run-wrangler-deploy`: Deploy using Wrangler 17 | - `run-wrangler-types`: Generate Wrangler types 18 | - `run-fix-deps`: Fix dependencies 19 | 20 | ### Runx CLI 21 | 22 | A TypeScript-based CLI for more complex automation tasks. While the bin scripts work well for simple tasks, the runx CLI provides better type safety and more sophisticated programmatic control. 23 | 24 | Usage: 25 | 26 | ```bash 27 | pnpm runx [options] 28 | ``` 29 | 30 | Available commands: 31 | 32 | - `deploy-published-workers`: Deploy Cloudflare Workers (based on which packages changesets marked as published in the release). 33 | 34 | Note: 35 | 36 | The CLI will automatically use Bun if available, but falls back to tsx if not installed. 37 | -------------------------------------------------------------------------------- /packages/tools/bin/run-changeset-new: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eu 3 | 4 | repo_root=$(git rev-parse --show-toplevel) 5 | cd "$repo_root" 6 | 7 | # Stage changes so that changeset can see them 8 | git add . 9 | 10 | changeset 11 | 12 | # Make sure a changeset was created 13 | git status --porcelain | grep '.changeset/.*\.md' >/dev/null && true || 14 | (echo "🚨 No changeset created" && exit 1) 15 | 16 | new_changeset=$(ls -t .changeset/*.md | head -n 1) 17 | echo "📝 New changeset: $new_changeset" 18 | git add "$new_changeset" -------------------------------------------------------------------------------- /packages/tools/bin/run-eslint-workers: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | args=( 5 | --cache 6 | --cache-strategy content 7 | --cache-location ./node_modules/.cache/eslint 8 | --max-warnings 1000 9 | . 10 | ) 11 | 12 | if [[ ! -z "${FIX_ESLINT:-}" ]]; then 13 | args+=("--fix") 14 | fi 15 | 16 | if [[ ! -z "${GITHUB_ACTIONS:-}" ]]; then 17 | args+=("--max-warnings=0") 18 | fi 19 | 20 | # get additional args 21 | while [[ $# -gt 0 ]]; do 22 | args+=("$1") 23 | shift 24 | done 25 | 26 | eslint "${args[@]}" 27 | -------------------------------------------------------------------------------- /packages/tools/bin/run-fix-deps: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | repo_root=$(git rev-parse --show-toplevel) 5 | cd "$repo_root" 6 | 7 | syncpack fix-mismatches 8 | -------------------------------------------------------------------------------- /packages/tools/bin/run-tsc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | tsc --noEmit -p tsconfig.json 5 | -------------------------------------------------------------------------------- /packages/tools/bin/run-turbo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Helper script for running turbo with tracking disabled 4 | # so that we don't have to export this env var everywhere. 5 | 6 | export DO_NOT_TRACK=1 7 | 8 | turbo "$@" 9 | -------------------------------------------------------------------------------- /packages/tools/bin/run-vitest: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | if test -f ./vitest.config.ts; then 5 | vitest run --testTimeout=15000 6 | elif test -f ./vitest.config.node.ts; then 7 | vitest run --testTimeout=15000 -c ./vitest.config.node.ts 8 | fi 9 | -------------------------------------------------------------------------------- /packages/tools/bin/run-vitest-ci: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | vitest run --silent --testTimeout=15000 5 | 6 | -------------------------------------------------------------------------------- /packages/tools/bin/run-wrangler-deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Extract name and version from package.json using jq 4 | NAME=$(jq -r '.name' package.json) 5 | VERSION=$(jq -r '.version' package.json) 6 | 7 | # Deploy with wrangler using the extracted values as binding variables 8 | echo "Deploying MCP server $NAME version $VERSION" 9 | wrangler deploy \ 10 | --var MCP_SERVER_NAME:"$NAME" \ 11 | --var MCP_SERVER_VERSION:"$VERSION" \ 12 | "$@" 13 | -------------------------------------------------------------------------------- /packages/tools/bin/run-wrangler-types: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | wrangler types --include-env=false 5 | -------------------------------------------------------------------------------- /packages/tools/bin/runx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -eu 3 | 4 | script_path="$(realpath "$(dirname "$0")/../src/bin/runx.ts")" 5 | 6 | bin_dir="$(realpath "$(dirname "$0")")" 7 | tsx_path="$(realpath "$bin_dir/../node_modules/.bin/tsx")" 8 | 9 | if command -v bun >/dev/null 2>&1; then 10 | bun "$script_path" "$@" 11 | else 12 | "$tsx_path" "$script_path" "$@" 13 | fi 14 | -------------------------------------------------------------------------------- /packages/tools/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/tools", 3 | "version": "0.33.1", 4 | "private": true, 5 | "sideEffects": false, 6 | "type": "module", 7 | "directories": { 8 | "bin": "bin" 9 | }, 10 | "devDependencies": { 11 | "@types/fs-extra": "11.0.4", 12 | "@types/node": "22.14.1", 13 | "vitest": "3.0.9" 14 | }, 15 | "dependencies": { 16 | "@commander-js/extra-typings": "13.1.0", 17 | "@jahands/cli-tools": "0.10.2", 18 | "commander": "13.1.0", 19 | "empathic": "1.1.0", 20 | "tsx": "4.19.3", 21 | "zod": "4.0.0-beta.20250505T195954", 22 | "zx": "8.5.4" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/tools/src/bin/runx.ts: -------------------------------------------------------------------------------- 1 | import 'zx/globals' 2 | 3 | import { program } from '@commander-js/extra-typings' 4 | import { catchProcessError } from '@jahands/cli-tools' 5 | 6 | import { deployPublishedWorkersCmd } from '../cmd/deploy-published-packages' 7 | 8 | program 9 | .name('runx') 10 | .description('A CLI for scripts that automate this repo') 11 | 12 | // While `packages/tools/bin` scripts work well for simple tasks, 13 | // a typescript CLI is nicer for more complex things. 14 | 15 | .addCommand(deployPublishedWorkersCmd) 16 | 17 | // Don't hang for unresolved promises 18 | .hook('postAction', () => process.exit(0)) 19 | .parseAsync() 20 | .catch(catchProcessError()) 21 | -------------------------------------------------------------------------------- /packages/tools/src/changesets.ts: -------------------------------------------------------------------------------- 1 | import { cliError, isNotFoundError } from '@jahands/cli-tools' 2 | import { z } from 'zod' 3 | 4 | export type PublishedPackage = z.infer 5 | export const PublishedPackage = z.object({ 6 | name: z.string(), 7 | version: z.string(), 8 | }) 9 | export const PublishedPackages = z.array(PublishedPackage) 10 | 11 | /** 12 | * Reads and parses the list of published packages from the runner's temporary directory. 13 | * This file is generated by the changesets action in the release workflow and contains 14 | * information about packages that were just published. 15 | * @returns Array of published packages 16 | * @throws Error if RUNNER_TEMP is not set, file is not found, or JSON parsing fails 17 | */ 18 | export async function getPublishedPackages(): Promise { 19 | const runnerTemp = await z 20 | .string({ error: '$RUNNER_TEMP is not set' }) 21 | .min(1, { error: '$RUNNER_TEMP is empty' }) 22 | .parseAsync(process.env.RUNNER_TEMP) 23 | .catch((e) => { 24 | throw cliError(z.prettifyError(e)) 25 | }) 26 | 27 | const publishedPackagesPath = path.join(runnerTemp, 'published-packages.json') 28 | 29 | echo(chalk.dim(`Reading published packages from ${publishedPackagesPath}`)) 30 | 31 | return fs 32 | .readFile(publishedPackagesPath, 'utf8') 33 | .then((s) => PublishedPackages.parse(JSON.parse(s))) 34 | .catch((e) => { 35 | if (isNotFoundError(e)) { 36 | throw cliError(`No published packages file found at: ${publishedPackagesPath}`) 37 | } else if (e instanceof z.ZodError) { 38 | throw new Error(`Failed to parse published packages: ${z.prettifyError(e)}`) 39 | } 40 | throw new Error(`Failed to parse published packages: ${e}`) 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /packages/tools/src/cmd/deploy-published-packages.ts: -------------------------------------------------------------------------------- 1 | import { Command } from '@commander-js/extra-typings' 2 | import { validateArg } from '@jahands/cli-tools' 3 | import z from 'zod' 4 | 5 | import { getPublishedPackages } from '../changesets' 6 | 7 | export const deployPublishedWorkersCmd = new Command('deploy-published-workers') 8 | .description( 9 | 'Deploy Cloudflare Workers (based on which packages changesets marked as published in the release)' 10 | ) 11 | .requiredOption( 12 | '-e, --env ', 13 | 'The environment to deploy to', 14 | validateArg(z.enum(['staging', 'production'])) 15 | ) 16 | .action(async ({ env }) => { 17 | const publishedPackages = await getPublishedPackages() 18 | 19 | // This technically includes all versioned packages (including non-Workers), 20 | // but that's fine because only Workers include a `deploy` package.json script. 21 | const filters = publishedPackages.flatMap((p) => ['-F', p.name]) satisfies string[] 22 | 23 | await $({ 24 | verbose: true, 25 | })`turbo deploy ${filters} -- --env ${env}` 26 | }) 27 | -------------------------------------------------------------------------------- /packages/tools/src/proc.ts: -------------------------------------------------------------------------------- 1 | export function getOutcome(exitCode: number | null) { 2 | if (exitCode === 0) { 3 | return chalk.green('Success!') 4 | } else { 5 | return chalk.red(`Failed with code: ${exitCode}`) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/tools/src/test/fixtures/changesets/empty/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudflare/mcp-server-cloudflare/main/packages/tools/src/test/fixtures/changesets/empty/.gitkeep -------------------------------------------------------------------------------- /packages/tools/src/test/fixtures/changesets/invalid-json/published-packages.json: -------------------------------------------------------------------------------- 1 | this is not valid json 2 | -------------------------------------------------------------------------------- /packages/tools/src/test/fixtures/changesets/invalid-schema/published-packages.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "package-a", 4 | "version": 123 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /packages/tools/src/test/fixtures/changesets/valid/published-packages.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "package-a", 4 | "version": "1.0.0" 5 | }, 6 | { 7 | "name": "package-b", 8 | "version": "2.1.3" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /packages/tools/src/test/setup.ts: -------------------------------------------------------------------------------- 1 | // Ensure chalk doesn't add colors to output for consistent snapshots 2 | delete process.env.FORCE_COLOR 3 | 4 | // runx uses zx/globals imported in bin/runx.ts 5 | // This import ensures that tests work without 6 | // needing to import this manually. 7 | await import('zx/globals') 8 | -------------------------------------------------------------------------------- /packages/tools/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/tools.json", 3 | "include": ["**/*.ts"], 4 | "exclude": ["node_modules", "tsconfig.json"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/tools/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config' 2 | 3 | export default defineConfig({ 4 | test: { 5 | setupFiles: [`${__dirname}/src/test/setup.ts`], 6 | environment: 'node', 7 | }, 8 | }) 9 | -------------------------------------------------------------------------------- /packages/typescript-config/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @repo/typescript-config 2 | 3 | ## 0.3.1 4 | 5 | ### Patch Changes 6 | 7 | - cc6d41f: Update agents deps & modelcontextprotocol 8 | 9 | ## 0.3.0 10 | 11 | ### Minor Changes 12 | 13 | - 6cf52a6: Support AOT tokens 14 | 15 | ### Patch Changes 16 | 17 | - 0fc4439: Update agents and modelcontext dependencies 18 | 19 | ## 0.2.5 20 | 21 | ### Patch Changes 22 | 23 | - bdb5b89: chore: remove publishConfig from typescript-config/package.json 24 | 25 | This did nothing. 26 | -------------------------------------------------------------------------------- /packages/typescript-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/typescript-config", 3 | "version": "0.3.1", 4 | "private": true, 5 | "sideEffects": false, 6 | "devDependencies": { 7 | "@types/node": "22.14.1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/typescript-config/tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Default", 4 | "compilerOptions": { 5 | "target": "es2022", 6 | "module": "es2022", 7 | "composite": false, 8 | "declaration": true, 9 | "declarationMap": true, 10 | "esModuleInterop": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "inlineSources": false, 13 | "isolatedModules": true, 14 | "moduleResolution": "node", 15 | "noUnusedLocals": false, 16 | "noUnusedParameters": false, 17 | "preserveWatchOutput": true, 18 | "skipLibCheck": true, 19 | "strict": true, 20 | "noEmit": true, 21 | "experimentalDecorators": true 22 | }, 23 | "exclude": ["node_modules"] 24 | } 25 | -------------------------------------------------------------------------------- /packages/typescript-config/workers-lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "@repo/typescript-config/workers.json", 4 | "include": ["${configDir}/**/*.ts", "${configDir}/**/*.tsx"], 5 | "exclude": ["${configDir}/node_modules/", "${configDir}/dist/"], 6 | "compilerOptions": { 7 | "types": ["@cloudflare/vitest-pool-workers"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/typescript-config/workers.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "include": [ 4 | "${configDir}/worker-configuration.d.ts", 5 | "${configDir}/env.d.ts", 6 | "${configDir}/**/*.ts", 7 | "${configDir}/**/*.tsx" 8 | ], 9 | "exclude": ["${configDir}/node_modules/", "${configDir}/dist/"], 10 | "compilerOptions": { 11 | "target": "es2022", 12 | "lib": ["es2022"], 13 | "jsx": "react", 14 | "module": "es2022", 15 | "moduleResolution": "bundler", 16 | "types": ["./worker-configuration.d.ts", "@cloudflare/vitest-pool-workers", "@types/node"], 17 | "resolveJsonModule": true, 18 | "allowJs": true, 19 | "checkJs": false, 20 | "noEmit": true, 21 | "isolatedModules": true, 22 | "allowSyntheticDefaultImports": true, 23 | "forceConsistentCasingInFileNames": true, 24 | "strict": true, 25 | "skipLibCheck": true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'apps/*' 3 | - 'packages/*' 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/tools.json" 3 | } 4 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "globalPassThroughEnv": ["FORCE_COLOR", "RUNNER_TEMP"], 4 | "tasks": { 5 | "deploy": { 6 | "cache": false, 7 | "env": ["CLOUDFLARE_ACCOUNT_ID", "CLOUDFLARE_API_TOKEN", "CLOUDFLARE_STAGING_API_TOKEN"], 8 | "outputs": ["dist"], 9 | "outputLogs": "new-only" 10 | }, 11 | "check": { 12 | "dependsOn": ["^check:types", "^check:lint", "check:types", "check:lint"], 13 | "outputLogs": "new-only" 14 | }, 15 | "check:types": { 16 | "dependsOn": ["^check:types"], 17 | "outputLogs": "new-only" 18 | }, 19 | "check:lint": { 20 | "env": ["GITHUB_ACTIONS"], 21 | "dependsOn": ["^check:lint"], 22 | "outputLogs": "new-only" 23 | }, 24 | "eval:ci": { 25 | "dependsOn": ["^eval:ci"], 26 | "outputLogs": "new-only" 27 | }, 28 | "types": { 29 | "dependsOn": ["^types"], 30 | "outputLogs": "new-only" 31 | }, 32 | "//#check:format": { 33 | "outputLogs": "new-only" 34 | }, 35 | "//#check:deps": { 36 | "outputLogs": "new-only" 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /vitest.workspace.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkspace } from 'vitest/config' 2 | 3 | export default defineWorkspace([ 4 | 'apps/*/vitest.config.ts', 5 | 'apps/*/vitest.config.node.ts', 6 | 'packages/*/vitest.config.ts', 7 | 'packages/*/vitest.config.node.ts', 8 | ]) 9 | --------------------------------------------------------------------------------