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: 5 additions & 4 deletions mcp-worker/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import OAuthProvider from '@cloudflare/workers-oauth-provider'
import OAuthProvider, { OAuthHelpers } from '@cloudflare/workers-oauth-provider'
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js'
import type { ZodRawShape } from 'zod'
Expand Down Expand Up @@ -54,6 +54,9 @@ export class DevCycleMCP extends McpAgent<Env, DevCycleMCPState, UserProps> {
WorkerApiClient.initializeMCPHeaders(this.version)

// Initialize the Worker-specific API client with OAuth tokens and state management
if (!this.props) {
throw new Error('User props not available')
}
this.apiClient = new WorkerApiClient(
this.props,
this.env,
Expand Down Expand Up @@ -158,12 +161,10 @@ export default {
// Create OAuth provider with env access
const provider = new OAuthProvider({
apiHandlers: {
// @ts-expect-error - type errors with the OAuthProvider
'/sse': DevCycleMCP.serveSSE('/sse'),
// @ts-expect-error - type errors with the OAuthProvider
'/mcp': DevCycleMCP.serve('/mcp'),
},
// @ts-expect-error - type erorrs with the OAuthProvider
// @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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
},
"dependencies": {
"@babel/parser": "^7.28.0",
"@modelcontextprotocol/sdk": "^1.17.1",
"@modelcontextprotocol/sdk": "^1.18.1",
"@oclif/core": "^2.16.0",
"@oclif/plugin-autocomplete": "^2.3.10",
"@oclif/plugin-help": "^6.2.27",
Expand Down
6 changes: 5 additions & 1 deletion src/api/apiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,8 @@ const apiClient: ApiClientType = _createApiClient(BASE_URL, {
export { apiClient }
export default apiClient

export const v2ApiClient = createV2ApiClient(BASE_URL)
// Create v2 API client using the same shared axiosClient instance to preserve MCP headers
export const v2ApiClient = createV2ApiClient(BASE_URL, {
axiosInstance: axiosClient,
validate: 'request',
})
42 changes: 21 additions & 21 deletions src/commands/features/__snapshots__/update.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,50 @@ exports[`features update > accepts flags and prompts for missing fields 1`] = `

🤖 Current values:
🤖 {
"name": "Feature Name",
"key": "feature-key",
"_id": "id",
"_project": "string",
"source": "api",
"name": "Feature Name",
"key": "feature-key",
"_createdBy": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"variations": [],
"controlVariation": "variation_id",
"variables": [],
"tags": [],
"ldLink": "string",
"readonly": true,
"settings": {},
"sdkVisibility": {
"mobile": true,
"client": true,
"server": true
}
},
"settings": {},
"controlVariation": "variation_id"
}


{
"name": "Feature Name",
"key": "feature-key",
"_id": "id",
"_project": "string",
"source": "api",
"name": "Feature Name",
"key": "feature-key",
"_createdBy": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"variations": [],
"controlVariation": "variation_id",
"variables": [],
"tags": [],
"ldLink": "string",
"readonly": true,
"settings": {},
"sdkVisibility": {
"mobile": true,
"client": true,
"server": true
}
},
"settings": {},
"controlVariation": "variation_id"
}
"
`;
Expand All @@ -58,58 +58,58 @@ exports[`features update > updates a feature after prompting for all fields 1`]

🤖 Current values:
🤖 {
"name": "Feature Name",
"key": "feature-key",
"_id": "id",
"_project": "string",
"source": "api",
"name": "Feature Name",
"key": "feature-key",
"_createdBy": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"variations": [],
"controlVariation": "variation_id",
"variables": [],
"tags": [],
"ldLink": "string",
"readonly": true,
"settings": {},
"sdkVisibility": {
"mobile": true,
"client": true,
"server": true
}
},
"settings": {},
"controlVariation": "variation_id"
}


🤖 No existing Variations.
🤖 No existing Variations.
----------------------------------------
{
"name": "Feature Name",
"key": "feature-key",
"_id": "id",
"_project": "string",
"source": "api",
"name": "Feature Name",
"key": "feature-key",
"_createdBy": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"variations": [],
"controlVariation": "variation_id",
"variables": [],
"tags": [],
"ldLink": "string",
"readonly": true,
"settings": {},
"sdkVisibility": {
"mobile": true,
"client": true,
"server": true
}
},
"settings": {},
"controlVariation": "variation_id"
}
"
`;

exports[`features update > updates a feature in headless mode 1`] = `
"{"_id":"id","_project":"string","source":"api","name":"Feature Name","key":"feature-key","_createdBy":"string","createdAt":"2019-08-24T14:15:22Z","updatedAt":"2019-08-24T14:15:22Z","variations":[],"controlVariation":"variation_id","variables":[],"tags":[],"ldLink":"string","readonly":true,"settings":{},"sdkVisibility":{"mobile":true,"client":true,"server":true}}
"{"name":"Feature Name","key":"feature-key","_id":"id","_project":"string","source":"api","_createdBy":"string","createdAt":"2019-08-24T14:15:22Z","updatedAt":"2019-08-24T14:15:22Z","variations":[],"variables":[],"tags":[],"ldLink":"string","readonly":true,"sdkVisibility":{"mobile":true,"client":true,"server":true},"settings":{},"controlVariation":"variation_id"}
"
`;
18 changes: 17 additions & 1 deletion src/mcp/utils/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as assert from 'assert'
import { DevCycleApiClient, handleZodiosValidationErrors } from './api'
import { DevCycleAuth } from './auth'
import { setMCPToolCommand } from './headers'
import { axiosClient } from '../../api/apiClient'
import { axiosClient, v2ApiClient } from '../../api/apiClient'

describe('DevCycleApiClient', () => {
let apiClient: DevCycleApiClient
Expand Down Expand Up @@ -185,5 +185,21 @@ describe('Header Management', () => {
expect(meta.command).to.equal('list_features')
expect(meta.caller).to.equal('mcp')
})

it('should ensure v2ApiClient uses shared axiosClient instance with MCP headers', () => {
// Set MCP headers on the shared axiosClient
setMCPToolCommand('create_feature')

// Verify that the v2ApiClient has access to the same headers
// This works because v2ApiClient should be using the shared axiosClient instance
const headers = axiosClient.defaults.headers.common as any
expect(headers['dvc-referrer']).to.equal('mcp')
const meta = JSON.parse(headers['dvc-referrer-metadata'])
expect(meta.command).to.equal('create_feature')
expect(meta.caller).to.equal('mcp')

// Verify v2ApiClient exists and is properly configured
expect(v2ApiClient).to.exist
})
})
})
22 changes: 1 addition & 21 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ __metadata:
"@babel/traverse": "npm:^7.28.0"
"@babel/types": "npm:^7.28.0"
"@eslint/js": "npm:^9.18.0"
"@modelcontextprotocol/sdk": "npm:^1.17.1"
"@modelcontextprotocol/sdk": "npm:^1.18.1"
"@oclif/core": "npm:^2.16.0"
"@oclif/plugin-autocomplete": "npm:^2.3.10"
"@oclif/plugin-help": "npm:^6.2.27"
Expand Down Expand Up @@ -1799,26 +1799,6 @@ __metadata:
languageName: node
linkType: hard

"@modelcontextprotocol/sdk@npm:^1.17.1":
version: 1.17.1
resolution: "@modelcontextprotocol/sdk@npm:1.17.1"
dependencies:
ajv: "npm:^6.12.6"
content-type: "npm:^1.0.5"
cors: "npm:^2.8.5"
cross-spawn: "npm:^7.0.5"
eventsource: "npm:^3.0.2"
eventsource-parser: "npm:^3.0.0"
express: "npm:^5.0.1"
express-rate-limit: "npm:^7.5.0"
pkce-challenge: "npm:^5.0.0"
raw-body: "npm:^3.0.0"
zod: "npm:^3.23.8"
zod-to-json-schema: "npm:^3.24.1"
checksum: 10c0/bddee1c4a90adb2ee3f89f5598f0499841b1ad8b4d9a52b2b0afac3009918570d72240588a17178e319bdfbe70aced190f66b25e14f0a0645eacaf4776d4c15a
languageName: node
linkType: hard

"@modelcontextprotocol/sdk@npm:^1.18.1":
version: 1.18.1
resolution: "@modelcontextprotocol/sdk@npm:1.18.1"
Expand Down