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
9 changes: 9 additions & 0 deletions mcp-worker/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Secrets set via `wrangler secret put`, not emitted by `wrangler types`.
// Declaration merging extends the generated Cloudflare.Env interface.
declare namespace Cloudflare {
interface Env {
AUTH0_CLIENT_ID: string
AUTH0_CLIENT_SECRET: string
ABLY_API_KEY: string
}
}
14 changes: 7 additions & 7 deletions mcp-worker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@
"test:watch": "vitest"
},
"dependencies": {
"@cloudflare/workers-oauth-provider": "^0.0.13",
"ably": "^1.2.48",
"agents": "^0.3.10",
"@cloudflare/workers-oauth-provider": "^0.3.0",
"ably": "^2.19.0",
"agents": "^0.7.6",
"hono": "^4.12.7",
"jose": "^6.1.0",
"oauth4webapi": "^3.8.1"
"jose": "^6.2.1",
"oauth4webapi": "^3.8.5"
},
"devDependencies": {
"@types/node": "^24.5.2",
"@types/node": "^25.4.0",
"vitest": "^3.2.4",
"wrangler": "^4.38.0"
"wrangler": "^4.72.0"
},
"packageManager": "yarn@4.9.2"
}
21 changes: 9 additions & 12 deletions mcp-worker/src/ably.test.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
import { afterEach, describe, expect, test, vi } from 'vitest'

// Lock Ably import and shape
vi.mock('ably/build/ably-webworker.min', () => {
vi.mock('ably', () => {
const publish = vi.fn()
const channelsGet = vi.fn(() => ({ publish }))
const channels = { get: channelsGet }

class RestPromiseMock {
public static Promise = vi.fn(() => new RestPromiseMock())
class RestMock {
public channels = channels
}

return { default: { Rest: RestPromiseMock } }
return { default: { Rest: vi.fn(() => new RestMock()) } }
})

import Ably from 'ably/build/ably-webworker.min'
import Ably from 'ably'
import { publishMCPInstallEvent } from './ably'

const getMocks = () => {
const Rest = (Ably as any).Rest as { Promise: any }
const instance =
Rest.Promise.mock.results[Rest.Promise.mock.results.length - 1]?.value
const Rest = (Ably as any).Rest as ReturnType<typeof vi.fn>
const instance = Rest.mock.results[Rest.mock.results.length - 1]?.value
const channelsGet = instance?.channels.get as ReturnType<typeof vi.fn>
const publish = channelsGet?.mock.results[0]?.value.publish as ReturnType<
typeof vi.fn
Expand All @@ -45,7 +43,7 @@ describe('publishMCPInstallEvent', () => {

const { Rest, instance, channelsGet, publish } = getMocks()

expect(Rest.Promise).toHaveBeenCalledWith({ key: env.ABLY_API_KEY })
expect(Rest).toHaveBeenCalledWith({ key: env.ABLY_API_KEY })
expect(instance).toBeDefined()
expect(channelsGet).toHaveBeenCalledWith('org_abc-mcp-install')
expect(publish).toHaveBeenCalledWith('mcp-install', {
Expand Down Expand Up @@ -89,9 +87,8 @@ describe('publishMCPInstallEvent', () => {
}

// Arrange the mock chain to throw on publish
const Rest = (await import('ably/build/ably-webworker.min')).default
.Rest as any
const instance = Rest.Promise()
const Rest = (await import('ably')).default.Rest as any
const instance = new Rest()
const channelsGet = vi.spyOn(instance.channels, 'get')
channelsGet.mockReturnValue({
publish: vi.fn(async () => {
Expand Down
4 changes: 2 additions & 2 deletions mcp-worker/src/ably.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Ably from 'ably/build/ably-webworker.min'
import Ably from 'ably'
import type { DevCycleJWTClaims } from './types'

export async function publishMCPInstallEvent(
Expand All @@ -17,7 +17,7 @@ export async function publishMCPInstallEvent(
const channel = `${claims.org_id}-mcp-install`

try {
const ably = new Ably.Rest.Promise({ key: env.ABLY_API_KEY })
const ably = new Ably.Rest({ key: env.ABLY_API_KEY })
const ablyChannel = ably.channels.get(channel)
const payload = {
org_id: claims.org_id,
Expand Down
1 change: 0 additions & 1 deletion mcp-worker/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ export default {
'/sse': DevCycleMCP.serveSSE('/sse'),
'/mcp': DevCycleMCP.serve('/mcp'),
},
// @ts-expect-error - Hono's fetch signature is compatible but TypeScript can't verify exact type match
defaultHandler: app,
authorizeEndpoint: '/oauth/authorize',
tokenEndpoint: '/oauth/token',
Expand Down
4 changes: 4 additions & 0 deletions mcp-worker/src/stubs/ai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Stub module for the "ai" (Vercel AI SDK) peer dependency.
// agents@0.7.x dynamically imports "ai" for features we don't use (AI chat, codemode).
// This stub satisfies the bundler without pulling in the full AI SDK.
export {}
1 change: 1 addition & 0 deletions mcp-worker/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"src/**/*",
"../src/**/*",
"worker-configuration.d.ts",
"env.d.ts",
"package.json"
],
"exclude": [
Expand Down
Loading
Loading