Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion apps/docs-autorag/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"scripts": {
"check:lint": "run-eslint-workers",
"check:types": "run-tsc",
"deploy": "wrangler deploy",
"deploy": "run-wrangler-deploy",
"dev": "wrangler dev",
"start": "wrangler dev",
"cf-typegen": "wrangler types",
Expand All @@ -16,6 +16,7 @@
"@hono/zod-validator": "0.4.3",
"@modelcontextprotocol/sdk": "1.9.0",
"@repo/mcp-common": "workspace:*",
"@repo/mcp-observability": "workspace:*",
"agents": "0.0.62",
"cloudflare": "4.2.0",
"hono": "4.7.6",
Expand All @@ -25,6 +26,7 @@
"devDependencies": {
"@cloudflare/vitest-pool-workers": "0.8.14",
"@cloudflare/workers-types": "4.20250410.0",
"@types/node": "^22.14.1",
"prettier": "3.5.3",
"typescript": "5.5.4",
"vitest": "3.0.9",
Expand Down
10 changes: 6 additions & 4 deletions apps/docs-autorag/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { McpAgent } from 'agents/mcp'
import { env } from 'cloudflare:workers'

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

import { registerDocsTools } from './tools/docs'

Expand All @@ -9,9 +11,9 @@ export type Props = never
export type State = never

export class CloudflareDocumentationMCP extends McpAgent<Env, State, Props> {
server = new McpServer({
name: 'Remote MCP Server with Cloudflare Documentation',
version: '1.0.0',
server = new CloudflareMCPServer(undefined, env.MCP_METRICS, {
name: env.MCP_SERVER_NAME,
version: env.MCP_SERVER_VERSION,
})

constructor(
Expand Down
7 changes: 5 additions & 2 deletions apps/docs-autorag/worker-configuration.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
/* eslint-disable */
// Generated by Wrangler by running `wrangler types` (hash: f47f9f62d3a1ddb9823a379fdafce5ce)
// Runtime types generated with workerd@1.20250417.0 2025-03-10 nodejs_compat
// Generated by Wrangler by running `wrangler types` (hash: 23bfeb1ecdb06845b72c16f50728901d)
// Runtime types generated with workerd@1.20250422.0 2025-03-10 nodejs_compat
declare namespace Cloudflare {
interface Env {
ENVIRONMENT: "development" | "staging" | "production";
AUTORAG_NAME: "cloudflare-docs-autorag";
MCP_SERVER_NAME: "PLACEHOLDER";
MCP_SERVER_VERSION: "PLACEHOLDER";
MCP_OBJECT: DurableObjectNamespace<import("./src/index").CloudflareDocumentationMCP>;
MCP_METRICS: AnalyticsEngineDataset;
AI: Ai;
}
}
Expand Down
27 changes: 23 additions & 4 deletions apps/docs-autorag/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,21 @@
},
"vars": {
"ENVIRONMENT": "development",
"AUTORAG_NAME": "cloudflare-docs-autorag"
"AUTORAG_NAME": "cloudflare-docs-autorag",
"MCP_SERVER_NAME": "PLACEHOLDER",
"MCP_SERVER_VERSION": "PLACEHOLDER"
},
"dev": {
"port": 8976
},
"workers_dev": false,
"preview_urls": false,
"analytics_engine_datasets": [
{
"binding": "MCP_METRICS",
"dataset": "mcp-metrics-dev"
}
],
"env": {
"staging": {
"name": "mcp-cloudflare-docs-autorag-staging",
Expand All @@ -54,10 +62,15 @@
"ENVIRONMENT": "staging",
"AUTORAG_NAME": "cloudflare-docs-autorag"
},

"ai": {
"binding": "AI"
}
},
"analytics_engine_datasets": [
{
"binding": "MCP_METRICS",
"dataset": "mcp-metrics-staging"
}
]
},
"production": {
"name": "mcp-cloudflare-docs-autorag-production",
Expand All @@ -77,7 +90,13 @@
},
"ai": {
"binding": "AI"
}
},
"analytics_engine_datasets": [
{
"binding": "MCP_METRICS",
"dataset": "mcp-metrics-production"
}
]
}
}
}
1 change: 1 addition & 0 deletions apps/sandbox-container/evals/exec.eval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@ eachModel('$modelName', ({ model }) => {
},
scorers: [checkFactuality],
threshold: 1,
timeout: 60000,
})
})
2 changes: 2 additions & 0 deletions apps/sandbox-container/evals/files.eval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ eachModel('$modelName', ({ model }) => {
},
scorers: [checkFactuality],
threshold: 1,
timeout: 60000,
})

describeEval('Runs container file delete', {
Expand Down Expand Up @@ -102,5 +103,6 @@ eachModel('$modelName', ({ model }) => {
},
scorers: [checkFactuality],
threshold: 1,
timeout: 60000,
})
})
1 change: 1 addition & 0 deletions apps/sandbox-container/evals/initialize.eval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ eachModel('$modelName', ({ model }) => {
},
scorers: [checkFactuality],
threshold: 1,
timeout: 60000,
})
})
5 changes: 3 additions & 2 deletions apps/sandbox-container/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
"postinstall": "mkdir -p workdir",
"test": "vitest",
"types": "wrangler types",
"eval:dev": "start-server-and-test --expect 404 eval:server http://localhost:8976 'vitest --config vitest.config.evals.ts'",
"eval:dev": "start-server-and-test --expect 404 eval:server http://localhost:8976 'vitest --testTimeout=60000 --config vitest.config.evals.ts'",
"eval:server": "concurrently \"tsx container/index.ts\" \"wrangler dev --var \"ENVIRONMENT:test\"\"",
"eval:ci": "start-server-and-test --expect 404 eval:server http://localhost:8976 'vitest run --config vitest.config.evals.ts'"
"eval:ci": "start-server-and-test --expect 404 eval:server http://localhost:8976 'vitest run --testTimeout=60000 --config vitest.config.evals.ts'"
},
"dependencies": {
"@cloudflare/workers-oauth-provider": "0.0.2",
Expand All @@ -26,6 +26,7 @@
"@n8n/json-schema-to-zod": "^1.1.0",
"@repo/eval-tools": "workspace:*",
"@repo/mcp-common": "workspace:*",
"@repo/mcp-observability": "workspace:*",
"@types/node": "^22.13.10",
"agents": "^0.0.62",
"cron-schedule": "^5.0.4",
Expand Down
2 changes: 0 additions & 2 deletions apps/sandbox-container/server/containerManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { DurableObject } from 'cloudflare:workers'

import { Env } from './index'

export class ContainerManager extends DurableObject<Env> {
constructor(
public ctx: DurableObjectState,
Expand Down
37 changes: 27 additions & 10 deletions apps/sandbox-container/server/containerMcp.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { McpAgent } from 'agents/mcp'

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

import { OPEN_CONTAINER_PORT } from '../shared/consts'
import { ExecParams, FilePathParam, FileWrite } from '../shared/schema'
import { MAX_CONTAINERS, proxyFetch, startAndWaitForPort } from './containerHelpers'
Expand All @@ -9,16 +10,21 @@ import { BASE_INSTRUCTIONS } from './prompts'
import { fileToBase64, stripProtocolFromFilePath } from './utils'

import type { FileList } from '../shared/schema'
import type { Env, Props } from '.'
import type { Props } from '.'

export class ContainerMcpAgent extends McpAgent<Env, {}, Props> {
_server: CloudflareMCPServer | undefined
set server(server: CloudflareMCPServer) {
this._server = server
}

get server(): CloudflareMCPServer {
if (!this._server) {
throw new Error('Tried to access server before it was initialized')
}

export class ContainerMcpAgent extends McpAgent<Env, Props> {
server = new McpServer(
{
name: 'Container MCP Agent',
version: '1.0.0',
},
{ instructions: BASE_INSTRUCTIONS }
)
return this._server
}

constructor(
public ctx: DurableObjectState,
Expand All @@ -44,6 +50,17 @@ export class ContainerMcpAgent extends McpAgent<Env, Props> {
}

async init() {
this.props.user.id
this.server = new CloudflareMCPServer(
this.props.user.id,
this.env.MCP_METRICS,
{
name: this.env.MCP_SERVER_NAME,
version: this.env.MCP_SERVER_VERSION,
},
{ instructions: BASE_INSTRUCTIONS }
)

this.server.tool(
'container_initialize',
'Start or reset the container',
Expand Down
24 changes: 15 additions & 9 deletions apps/sandbox-container/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
createAuthHandlers,
handleTokenExchangeCallback,
} from '@repo/mcp-common/src/cloudflare-oauth-handler'
import { MetricsTracker } from '@repo/mcp-observability'

import { ContainerManager } from './containerManager'
import { ContainerMcpAgent } from './containerMcp'
Expand All @@ -14,13 +15,10 @@ import type { AccountSchema, UserSchema } from '@repo/mcp-common/src/cloudflare-

export { ContainerManager, ContainerMcpAgent }

export type Env = {
CONTAINER_MCP_AGENT: DurableObjectNamespace<ContainerMcpAgent>
CONTAINER_MANAGER: DurableObjectNamespace<ContainerManager>
ENVIRONMENT: 'dev' | 'prod' | 'test'
CLOUDFLARE_CLIENT_ID: string
CLOUDFLARE_CLIENT_SECRET: string
}
const metrics = new MetricsTracker(env.MCP_METRICS, {
name: env.MCP_SERVER_NAME,
version: env.MCP_SERVER_VERSION,
})

// Context from the auth process, encrypted & stored in the auth token
// and provided to the DurableMCP as this.props
Expand All @@ -41,8 +39,16 @@ const ContainerScopes = {

export default {
fetch: (req: Request, env: Env, ctx: ExecutionContext) => {
// @ts-ignore
if (env.ENVIRONMENT === 'test') {
ctx.props = {}
ctx.props = {
accessToken: 'foobar',
user: {
id: '123def',
email: '[email protected]',
},
accounts: [],
} as Props
return ContainerMcpAgent.mount('/sse', { binding: 'CONTAINER_MCP_AGENT' }).fetch(
req,
env as Record<string, DurableObjectNamespace<McpAgent> | any>,
Expand All @@ -55,7 +61,7 @@ export default {
// @ts-ignore
apiHandler: ContainerMcpAgent.mount('/sse', { binding: 'CONTAINER_MCP_AGENT' }),
// @ts-ignore
defaultHandler: createAuthHandlers({ scopes: ContainerScopes }),
defaultHandler: createAuthHandlers({ scopes: ContainerScopes, metrics }),
authorizeEndpoint: '/oauth/authorize',
tokenEndpoint: '/token',
tokenExchangeCallback: (options) =>
Expand Down
Loading